D3.js缩放状态下添加元素后取消缩放位置异常如何解决
D3.js 缩放状态添加元素位置偏移问题修复方案
根因说明
- D3 的缩放行为本质是通过给容器设置
transform属性实现视觉上的缩放平移,你在缩放状态下直接获取的点击坐标是经过变换后的相对坐标,不属于容器的原始坐标系 - 当你撤销缩放后容器的
transform重置,之前用相对坐标设置位置的元素自然会出现偏移
正确实现逻辑
所有在缩放状态下动态添加的元素,坐标都需要先转换为原始坐标系的绝对坐标再赋值,具体操作如下:
- 绑定 zoom 事件时保留当前的变换实例,不要只修改 DOM 的样式属性
- 点击添加元素时,调用当前 transform 实例的
invert()方法,把点击获取的视口坐标转换为原始坐标系坐标 - 用转换后的原始坐标设置元素的位置属性即可
核心代码示例
// 初始化zoom实例 const zoom = d3.zoom() .scaleExtent([0.5, 3]) .on("zoom", (event) => { // 给内容容器应用变换 contentGroup.attr("transform", event.transform); }); // 给外层svg绑定zoom行为 svg.call(zoom); // 绑定点击添加元素事件 svg.on("click", (event) => { // 获取当前容器的zoom变换实例 const currentTransform = d3.zoomTransform(svg.node()); // 将点击坐标转换为原始坐标系下的坐标 const [originX, originY] = currentTransform.invert(d3.pointer(event)); // 用原始坐标添加circle元素 contentGroup.append("circle") .attr("cx", originX) .attr("cy", originY) .attr("r", 4) .attr("fill", "#f00"); });
注意点
- 不要直接用
event.clientX、event.offsetX这类原生事件返回的坐标作为元素的位置值,缩放状态下这类坐标和原始坐标系不匹配 - 平移操作下添加元素也可以用同样的逻辑处理,坐标都不会出现偏移
内容的提问来源于stack exchange,提问作者ass-king some questions
相关产品推荐
相关产品推荐

