我正在使用D3 V4。我显示的树状图看起来基本上是这样的:https://bl.ocks.org/mbostock/4339184
我正在尝试实施拖动和缩放。我还有一个应用于zoomIdentity的变换,可以在第一次渲染时将地图移动一个固定的数量(margin.left和margin.top);
此post似乎与我的问题最为接近,但当我尝试将svg
与g
分开时,拖累非常不稳定。当我拖动时,每个节点都会跳跃并跳转。使用下面显示的代码,拖动是平滑的,但是最初的拖动会将所有节点向左移动(d3.event.transform x:0,y:0)。
let margin = { top: 20, right: 120, bottom: 20, left: 120 },
width = 1000 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
let zoom = d3.zoom();
let transform = d3.zoomIdentity.translate(margin.left, margin.top);
let svg = d3
.select("#map")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.call(zoom
.on("zoom", () => {
svg.attr("transform", d3.event.transform)
}))
.append("g")
.attr("class", "view")
svg.call(zoom.transform, transform)
我不确定我做错了什么,或者特别是为什么svg的内容都是生涩的。
答案 0 :(得分:1)
生活很有趣,有时候!
根据Mark的建议,我创建了一个代码示例。令我惊讶的是,它奏效了。所以我总结说它必须是其他一些问题(我真正的树是模态等)。
在清理沙盒的代码时,我做了以下更改,几乎是随机的:
let transform = d3.zoomIdentity.translate(margin.left, margin.top);
let zoom = d3.zoom();
let svg = d3
.select("#map")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.call(d3.zoom()
.on("zoom", () => {
svg.attr("transform", d3.event.transform)
}))
.call(zoom.transform, transform)
.append("g")
.attr("class", "view")
.attr("transform", transform)
当我将相同的代码应用于我的实际代码时,一切都运行得很好。我不完全理解为什么会这样,但我认为它与再次调用d3.zoom()
有关,而不是存储对它的引用。如果比我更有知识的人发表评论,我会将这个解释纳入我的答案。
答案 1 :(得分:1)
你的代码是按照书面编写的,因为你在Map.js中使用第43行很幸运,你手动应用了变换以防止它“跳跃”。
.attr("transform", transform)
保持对缩放的引用无关紧要,如docs state:
缩放行为将缩放状态存储在元素所在的元素上 应用了缩放行为,而不是缩放行为本身。这是 因为缩放行为可以应用于许多元素 同时,每个元素可以独立缩放。变焦 状态可以改变用户交互或通过编程方式改变 zoom.transform。
为了记录,这是我将如何编码:
let transform = d3.zoomIdentity.translate(margin.left, margin.top);
// create zoom
let zoom = d3.zoom().on("zoom", () => {
svg.attr("transform", d3.event.transform);
});
// create svg apply zoom to it
// svg becomes the event handler
// storing as p to avoid confusion
let p = d3
.select("#map")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.call(zoom);
// create g, store as svg, so I don't have to refactor code later
let svg = p
.append("g")
.attr("class", "view");
// apply initial transform to g by acting on svg
p.call(zoom.transform, transform);
这是一个forked codesandbox。这是一个很酷的网站,BTW,不知道这一点。