gpt4 book ai didi

javascript - D3 地理 map 缩放无法正常工作(Canvas)

转载 作者:行者123 更新时间:2023-11-30 20:17:35 29 4
gpt4 key购买 nike

我正在尝试在 Canvas 中缩放 map 。

var projection = d3.geoMercator()
projection.fitExtent([[margin.left, margin.top], [width, height]], land);
var path = d3.geoPath().projection(projection).context(context);

当我将平移和缩放应用到 Canvas 上下文时,它工作得很好。但是当我调用 var latlong = projection.invert(d3.mouse(this)); 时,它不会返回正确的纬度和经度,因为投影没有相应地转换。

var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.on("zoom", zoomByContext);

function zoomByContext() {
var transform = d3.event.transform;
context.clearRect(0, 0, width, height);
context.save();
context.translate(transform.x, transform.y);
context.lineWidth = 0.5 / transform.k;
context.scale(transform.k, transform.k);
renderFeature();
context.restore();
}

所以我尝试像打击一样重新投影投影。但是当我使用以下代码缩放时它会转到左上角。

var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.on("zoom", zoomByProjection);

function zoomByProjection() {
var transform = d3.event.transform;
projection.translate([transform.x, transform.y]);
projection.scale(scale * transform.k);
renderFeature();
}

我这样称呼缩放

canvas.call(zoom, d3.zoomIdentity
.translate(projection.translate())
.scale(projection.scale()));

最佳答案

对于第一种方法,您需要先反转缩放,然后再将 xy 坐标转换为长纬度坐标:

var transform = d3.zoomTransform(this);
var xy = transform.invert(d3.mouse(this));
var longlat = projection.invert(xy);

我们在像素坐标中获取鼠标位置,将其转​​换为缩放坐标,然后将其转换为地理坐标。

这应该证明以上内容:

var width = 960;
var height = 500;

var canvas = d3.select("canvas");
var context = canvas.node().getContext("2d")
var projection = d3.geoMercator();
var path = d3.geoPath(projection,context);


d3.json("https://unpkg.com/world-atlas@1/world/110m.json", function(error, world) {
if (error) throw error;

renderFeature();

var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.on("zoom", zoomByContext);

canvas.call(zoom);

function zoomByContext() {
var transform = d3.event.transform;
context.clearRect(0, 0, width, height);
context.save();
context.translate(transform.x, transform.y);
context.lineWidth = 0.5 / transform.k;
context.scale(transform.k, transform.k);
renderFeature();
context.restore();
}
function renderFeature() {
context.beginPath();
path(topojson.mesh(world));
context.stroke();
}

canvas.on("click", function() {
var transform = d3.zoomTransform(this);
var xy = transform.invert(d3.mouse(this));
var longlat = projection.invert(xy);
console.log(longlat);
})



});
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>

第二种方法有点棘手,如果投影的转换是 [0,0],您所采用的方法将起作用,但这种情况很少见。默认值为[480,250](假设 Canvas 为960x500),fitSizefitExtent不通过修改rotate来定位特征和中心,而是翻译。因此,您需要在修改投影时考虑初始翻译(就像您对比例所做的那样):

var transform = d3.event.transform;
projection.translate([transform.x+translate[0]*transform.k, transform.y+translate[1]*transform.k]);
projection.scale(scale * transform.k);

这里的 translate 是一个包含初始翻译值的数组

这里有一个演示可以证明以上内容:

var width = 960;
var height = 500;

var canvas = d3.select("canvas");
var context = canvas.node().getContext("2d")
var projection = d3.geoMercator().center([105,3]).scale(1200).translate([2000,0]);
var path = d3.geoPath(projection,context);
var scale = projection.scale();
var translate = projection.translate();



d3.json("https://unpkg.com/world-atlas@1/world/110m.json", function(error, world) {
if (error) throw error;

renderFeature();

var zoom = d3.zoom()
.scaleExtent([0.1, Infinity])
.on("zoom", zoomByProjection);

canvas.call(zoom);

function zoomByProjection() {
context.clearRect(0, 0, width, height);
var transform = d3.event.transform;
projection.translate([transform.x+translate[0]*transform.k, transform.y+translate[1]*transform.k]);
projection.scale(scale * transform.k);
renderFeature();
}

function renderFeature() {
context.beginPath();
path(topojson.mesh(world));
context.stroke();
}

});
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>

关于javascript - D3 地理 map 缩放无法正常工作(Canvas),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51781052/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com