在缩放时无法翻译初始d3.zoomIdentity而没有急动

时间:2018-02-12 02:29:58

标签: javascript d3.js svg

我正在使用D3 V4。我显示的树状图看起来基本上是这样的:https://bl.ocks.org/mbostock/4339184

我正在尝试实施拖动和缩放。我还有一个应用于zoomIdentity的变换,可以在第一次渲染时将地图移动一个固定的数量(margin.left和margin.top);

post似乎与我的问题最为接近,但当我尝试将svgg分开时,拖累非常不稳定。当我拖动时,每个节点都会跳跃并跳转。使用下面显示的代码,拖动是平滑的,但是最初的拖动会将所有节点向左移动(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的内容都是生涩的。

2 个答案:

答案 0 :(得分:1)

生活很有趣,有时候!

根据Mark的建议,我创建了一个代码示例There is an extra level of directories。令我惊讶的是,它奏效了。所以我总结说它必须是其他一些问题(我真正的树是模态等)。

在清理沙盒的代码时,我做了以下更改,几乎是随机的:

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,不知道这一点。