简体   繁体   English

不缩放就无法翻译初始d3.zoomIdentity

[英]Cannot translate initial d3.zoomIdentity without jerkiness on zoom

I'm using D3 V4. 我正在使用D3 V4。 I'm displaying a tree map that looks essentially like this: https://bl.ocks.org/mbostock/4339184 我正在显示本质上看起来像这样的树图: https : //bl.ocks.org/mbostock/4339184

I'm trying to implement drag and zoom. 我正在尝试实现拖动和缩放。 I also have a transform applied to the zoomIdentity to shift the map over by a fixed amount on first render (margin.left and margin.top); 我还对zoomIdentity进行了转换,以在第一个渲染(margin.left和margin.top)上将地图移动固定的数量;

This post seems the closest to my issue, but when I try to separate the svg from the g , the drag is extremely jerky. 这篇文章似乎与我的问题最接近,但是当我尝试将svgg分开时,拖动非常困难。 Each of the nodes jerks and jumps around as I drag. 当我拖动时,每个节点都会抽动并跳来跳去。 With the code presented below, the drag is smooth, but the very initial drag moves all the nodes to the left (d3.event.transform x: 0, y: 0). 使用下面提供的代码,拖动是平滑的,但是最开始的拖动将所有节点移到左侧(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)

I'm not sure what I'm doing wrong or specifically why the content of the svg is all jerky. 我不确定自己在做什么错,也不确定为什么svg的内容全都是生涩的。

Life is funny, sometimes! 生活有时很有趣!

Following Mark's suggestion, I created a code sample here . 按照Mark的建议,我在这里创建了一个代码示例。 To my surprise, it worked. 令我惊讶的是,它奏效了。 So I concluded it must be some other issue (my real tree is in a modal, etc.). 因此,我得出结论,这肯定是其他问题(我的真实树在模式中,等等)。

In cleaning up the code for the sandbox, I made the following changes, almost at random: 在清理沙箱的代码时,我几乎随机地进行了以下更改:

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)

When I applied the same code to my actual code, everything just worked perfectly. 当我将相同的代码应用于实际代码时,一切都可以正常工作。 I don't entirely understand why this works, but I think it has something to do with calling d3.zoom() again, rather than storing a reference to it. 我不完全理解为什么这样做,但是我认为这与再次调用d3.zoom() ,而不是存储对它的引用。 If someone more knowledgeable than me could comment I will incorporate that explanation into my answer. 如果某人比我更有知识,可以发表评论,我会将其解释纳入我的回答。

Your code works as written because you got lucky with line 43 in Map.js, you manually applied the transform to keep it from "jumping". 您的代码可以编写,因为您对Map.js中的第43行很幸运,因此您手动应用了转换以防止其“跳转”。

 .attr("transform", transform)

Keeping a reference to the zoom doesn't matter, as the docs state : 保留对缩放的引用并不重要,因为docs指出

The zoom behavior stores the zoom state on the element to which the zoom behavior was applied, not on the zoom behavior itself. 缩放行为将缩放状态存储在应用了缩放行为的元素上,而不是存储在缩放行为本身上。 This is because the zoom behavior can be applied to many elements simultaneously, and each element can be zoomed independently. 这是因为缩放行为可以同时应用于多个元素,并且每个元素都可以独立缩放。 The zoom state can change either on user interaction or programmatically via zoom.transform. 缩放状态可以在用户交互时更改,也可以通过zoom.transform以编程方式更改。

For the record, here's how I would have coded it: 作为记录,这是我的编码方式:

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);

Here's a forked codesandbox . 这是一个分叉的codeandbox That's a cool site, BTW, didn't know about that. 顺便说一句,BTW真是个不错的网站。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM