javascript - 将 SVG 矢量平铺地图转换为使用 Canvas 时出现问题
问题描述
我正在制作一张加拿大选举投票区的可视化地图。我设法在这里获得了一个有效的 SVG 版本。
然而,性能很差,所以我想我会改为在 Canvas 上绘图。我把我认为是直接转换的东西放在一起:
class VectorMap {
constructor(map_file, element_id) {
this.map_file = map_file;
this.root = $(`#${element_id}`)[0];
this.init_map();
}
init_map() {
var root_rect = this.root.getBoundingClientRect();
this.width = root_rect.width;
this.height = 720;
this.zoom = d3.zoom()
.on('zoom', _ => this.onZoom(d3.event.transform));
var canvas = d3.select(this.root).append('canvas')
.attr('width', this.width)
.attr('height', this.height)
.call(this.zoom);
this.context = canvas.node().getContext('2d');
this.projection = d3.geoMercator()
.scale(1 / 2 / Math.PI)
.translate([0, 0]);
this.path = d3.geoPath()
.projection(this.projection)
.context(this.context);
this.onZoom(d3.zoomIdentity);
}
onZoom(transform) {
var tiler = d3.tile()
.size([this.width, this.height])
.scale(transform.k)
.translate([transform.x, transform.y])
//init drawing parameters
this.context.save();
this.context.fillStyle = 'gray';
this.context.strokeStyle = 'red';
//this.context.lineWidth = 1 / transform.k;
this.context.setTransform(1, 0, 0, 1, 0, 0);
this.context.clearRect(0, 0, this.width, this.height);
this.context.scale(transform.k, transform.k);
this.context.translate(transform.x, transform.y);
var tiles = tiler();
tiles.forEach(tile => {
console.log(tile);
var zoom = tile[2];
var x = tile[0];
var y = tile[1];
if (zoom > 10) {
// since these are vector tiles we can just overzoom the z10 ones
x = Math.floor(x / Math.pow(2, zoom - 10));
y = Math.floor(y / Math.pow(2, zoom - 10));
zoom = 10;
}
d3.json(`/maps/${zoom}/${x}/${y}/`)
.then(function(json) {
json.features.forEach(feature => {
this.context.beginPath();
path(feature);
this.context.closePath();
this.context.stroke();
this.context.fill();
});
});
});
this.context.restore();
}
但它什么也没画。显然 SVG 和 Canvas 之间发生了一些变化,但我不确定是什么。只是绘制矩形似乎有效,所以我假设这是画布路径生成器的问题。
解决方案
推荐阅读
- elasticsearch - 如何使用 GET 响应 Curl Kibana 仪表板以查找所有仪表板 ID 和/或仪表板内容
- string - 没有引用计数的交换字符串
- r - 如何使用for循环在R中的数据框名称中使用i创建新的数据框
- lua - 尝试用“Touched”索引 nil?
- base64 - 用于身份验证的 Base64
- php - 是否可以将 $_SESSION 变量保存到数组中?
- python - 试图让 tensorflow 2 与 WSL 2 一起工作时遇到问题
- javascript - 记忆游戏翻转单张卡片不起作用 - JavaScript
- android - 过滤编号的 ArrayList
包含 android 中的重复项 - pipenv - 如何使用 && 使用 pipenv 脚本运行两个命令?