D3.js在画布和svg中映射缩放行为
D3.js map zoom behaviors in canvas and svg
感谢阅读。
目标
我想将工作中的SVG点击缩放从Mike Bostock的块与基于画布的系统进行比较。我把正在工作的SVG放在顶部,把画布放在底部。当用户单击上部SVG中的状态时,我希望下部画布元素"跟随"或模仿缩放和平移。例如,在上部SVG中单击Minnesota也会导致下部画布缩放并平移到Minnesota。
问题
我的画布元素在加载topojson后绘制得很好,但它没有动画。我希望它有动画效果。我相信这是因为我不完全理解缩放行为和基于路径的投影。
http://jsfiddle.net/30w8nv4t/2/
function zoomed(d) {
g.style("stroke-width", 1.5 / d3.event.scale + "px");
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
// the zTranslate and zScale variables appear to be ok,
// but `d` is null. I'm not sure how to redraw.
var zTranslate = zoom.translate();
var zScale = zoom.scale();
console.log(zTranslate, zScale, d);
context.clearRect(0, 0, width, height);
context.beginPath();
canvasPath(d);
context.stroke();
}
在这种情况下,d
显然为null,因此我无法重新绘制任何内容。我想我的问题可能在zoomed
方法或clicked
函数中。
原因
我之所以使用这种并排的方法,是因为我想了解路径、投影和缩放行为是如何协同工作的。我很欣赏canvas在SVG上的表现,但缺乏交互性让人望而却步。幸运的是,能够缩放和平移到任意几何图形将我的问题减半。
感谢您的阅读。JSFiddle的链接在这篇文章的顶部。
canvas
绘图函数使用纬度/经度坐标的投影值,但您没有在zoom
处理程序中更新projection
的scale
和translate
。
获得所追求的行为的一种方法是从zoom
处理程序中svg
上的transform
切换到projection
上的transform
。
我在这个更新的小提琴中做到了这一点:http://jsfiddle.net/30w8nv4t/7/
区别在于:
-
更新
zoom
行为以使用projection
translate
和scale
作为默认值,并将scaleExtent
值设置为基于projection
。var zoom = d3.behavior.zoom() .translate(projection.translate()) .scale(projection.scale()) .scaleExtent([projection.scale()/5, projection.scale()*5]) .on("zoom", zoomed);
-
将
zoomed
函数更新为translate
,将scale
更新为projection
,然后重新绘制基于svg
的路径。function zoomed(d) { //g.style("stroke-width", 1.5 / d3.event.scale + "px"); //g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); projection.translate(d3.event.translate).scale(d3.event.scale); g.selectAll("path").attr("d", path); var zTranslate = zoom.translate(); var zScale = zoom.scale(); console.log(zTranslate, zScale, d); context.clearRect(0, 0, width, height); context.beginPath(); canvasPath(states); context.stroke(); }
-
相应地更新您的
clicked
函数。function clicked(d) { if (active.node() === this) { zoom.scale(500).translate([width/2, height/2]); active.classed("active", false); active = d3.select(null); } else { var centroid = path.centroid(d), translate = zoom.translate(), bounds = path.bounds(d), dx = bounds[1][0] - bounds[0][0], dy = bounds[1][1] - bounds[0][1], scale = .9/ Math.max(dx / width, dy / height); zoom.scale(scale * zoom.scale()) .translate([ translate[0] - centroid[0] * scale + width * scale / 2, translate[1] - centroid[1] * scale + height * scale / 2]); active.classed("active", false); active = d3.select(this).classed("active", true); } zoom.event(svg); }
这可能是变化的主要组成部分之一,因为
scale
和translate
被应用于zoom
行为,当它们被应用时,它们必须按当前zoom
scale
进行缩放。clicked
函数随后触发zoomed
函数以重新绘制svg
和canvas
元素。
如您所见,您的canvas
绘图代码是正确的。只是的绘制代码使用projection
来确定要绘制的点的x
和y
位置,而projection
没有被zoom
处理程序更新。
对于canvas
,也可以有一个单独的projection
,并在调用canvas
重绘函数之前在zoom
处理程序中更新它。我将把它留给读者练习!
- 更改高贴图的缩放级别
- 在不阻止默认行为的情况下检测IE10中的缩放
- 单击超链接时,如何使用Google Maps API v3缩放地图
- 缩放Raphael/SVG容器以适应所有内容
- 传单缩放控制位置错误
- 在不移动内部文本的情况下缩放元素的效果
- 调整缩放窗口高度提升缩放
- 计算CSS3缩放框在另一个框中的最高位置
- D3.JS向rect添加缩放和列表项
- 当我在节点上拖动鼠标时,我如何防止使用d3.ehavior.zoom().on(“缩放”,重绘)
- 将直流图表库中的折线图缩放限制为小时
- D3.js在画布和svg中映射缩放行为
- D3:将鼠标滚轮重新映射为平移手势,而不是缩放手势
- D3.JS树映射不一致的缩放行为
- D3.js节点映射中的缩放功能
- 必应地图加载映射() 函数缩放参数
- 如何查看映射绑定缩放级别
- 创建一个映射回调,按数组和缩放每个数组值
- 图像映射区域突出显示和使用 iScroll 4 缩放
- 这里映射了如何在双击时禁用缩放