D3缩放后如何重置zoom.transform且不重置已有的选择内容
解决方案
你要的效果可以通过两种方式实现,以下是具体实现方法:
方案1:每次事件处理后重置zoom内部累计状态
d3的zoom行为的变换状态是存储在绑定该行为的DOM元素上,而非zoom实例本身,你可以主动调用zoom.transform方法将状态重置为d3.zoomIdentity,注意要避免主动重置操作触发回调导致死循环:
// 提前保存绑定zoom行为的容器选择集,对应你初始化时call(zoom)的元素 const zoomContainer = d3.select('#your-zoom-container'); const zoom = d3.zoom(); zoom.on("zoom", event => { // 跳过我们主动重置触发的事件,避免死循环 if (event.sourceEvent?.skipReset) return; // 这里拿到的event.transform就是本次操作的增量值 console.log(event.transform); recalculateVertices(event.transform); recalculateEdges(event.transform); // 重置zoom内部累计状态为初始值 zoomContainer.call( zoom.transform, d3.zoomIdentity, { skipReset: true } ); }) // 初始化绑定zoom行为 zoomContainer.call(zoom);
方案2:手动维护上一次变换状态计算增量
如果你不想修改zoom的内部状态,也可以自己维护上一次的变换值,手动计算两次事件之间的增量:
// 存储上一次事件的变换值,初始为单位矩阵 let lastTransform = d3.zoomIdentity; d3.zoom().on("zoom", event => { // 计算本次操作的增量变换 const deltaTransform = d3.zoomIdentity .translate(event.transform.x - lastTransform.x, event.transform.y - lastTransform.y) .scale(event.transform.k / lastTransform.k); // 用增量值执行业务逻辑 recalculateVertices(deltaTransform); recalculateEdges(deltaTransform); // 更新存储的上一次变换值 lastTransform = event.transform; })
两种方案都可以实现你要的效果,方案1的逻辑更简单,方案2不需要修改zoom的内置状态,适合需要保留累计变换值的场景。
内容的提问来源于stack exchange,提问作者Rahat Zaman
相关产品推荐
相关产品推荐

