简体   繁体   English

如何偏移d3 zoom的初始起始位置?

[英]How can I offset the initial starting position of a d3 zoom?

I'm trying to zoom in on an SVG element after having translated it's Matrix, but when I start the initial zoom, the position of the SVG resets to 0,0. 我试图在翻译它的矩阵之后放大SVG元素,但是当我开始初始缩放时,SVG的位置重置为0,0。 I'd like the zoom and pan to start from the moved position on page load. 我希望缩放和平移从页面加载时移动的位置开始。

<svg id="#svg">
   <g id="#mainGrid>
     ....a bunch of SVG
   </g>
<svg>

<script>
var winCenterV = $(window).height()/2;
var winCenterH = $(window).width()/2;

//set mainGrid to the center of window using snap.svg
var mainGrid = Snap.select("#mainGrid");
var myMatrix = new Snap.Matrix();
myMatrix.scale(1,1);            
myMatrix.translate(winCenterH,winCenterV);
myMatrix.rotate(0); 
mainGrid.transform(myMatrix); 


//d3 zoom
var svgElement = d3.select("svg");
var gridELement = d3.select("#mainGrid");

svgElement.call(d3.zoom()
    .scaleExtent([1 / 2, 4])
    .on("zoom", zoomed));

function zoomed() {
  gridELement.attr("transform", d3.event.transform);
}

</script>

the "mainGrid" SVG element zooms and pans fine, but it snaps back to it's 0,0 position (top left of browser) during the first zoom mouse click or wheel scroll instead of zooming and panning from the transformed location as set by myMatrix. “mainGrid”SVG元素缩放和平移很好,但它在第一次缩放鼠标单击或滚轮滚动期间快速回到它的0,0位置(浏览器的左上角),而不是从myMatrix设置的变换位置进行缩放和平移。 How can I get the d3.event.transform to start zooming from this offset? 如何让d3.event.transform从这个偏移量开始缩放?

Problem: 问题:

The d3 zoom behavior does not track or know about what transforms you've applied to an element. d3缩放行为不会跟踪或了解您应用于元素的变换。 It is initialized with scale equal to 1 and translate equal to 0,0. 它的初始化等级为1,平移等于0,0。 So, when you use 所以,当你使用

gridELement.attr("transform", d3.event.transform);

in your zoomed function, you are zooming relative to this initial scale and translate. 在缩放功能中,您相对于此初始比例进行缩放并进行平移。

Rationale 合理

Not every d3 zoom manipulates the transform of the SVG element it is called on: you may want to have zoom interaction everywhere on a plot, but only zoom the plot area and not the margins. 并非每个d3缩放都会操纵调用它的SVG元素的变换:您可能希望在绘图上的任何位置都进行缩放交互,但只能缩放绘图区域而不是边距。 Many d3 zooms don't manipulate any SVG transform: they may use semantic zooming, or the zoom may be altering a canvas rather than SVG, etc. As such, a d3-zoom behavior is independent of any SVG transorm attribute on the element(s) it is called on. 许多d3缩放不会操纵任何SVG变换:它们可能使用语义缩放,或者缩放可能正在改变画布而不是SVG等。因此,d3缩放行为独立于元素上的任何SVG变换属性( s)它被召唤。

Solution

If your zooming by manipulating the transform attribute of an SVG element, let D3 zoom do all of the manipulation - no need to manipulate it manually and have a zoom, this is how the zoom gets out of step. 如果通过操纵SVG元素的transform属性进行缩放,让D3缩放完成所有操作 - 无需手动操作并进行缩放,这就是缩放失步的方法。

So, 所以,

You can programmatically trigger a zoom event prior to rendering anything. 您可以在渲染任何内容之前以编程方式触发缩放事件。 The easiest way to do so is to use: 最简单的方法是使用:

selection.call(zoom.transform, d3.zoomIdentity.translate(x,y).scale(k));

This line triggers a zoom event. 该行触发缩放事件。 We can use this prior to rendering anything and rely on the zoomed function to set the initial value of the SVG transform attribute. 我们可以在渲染任何东西之前使用它,并依靠缩放函数来设置SVG变换属性的初始值。 All subsequent zooms will be relative to this and we can proceed as normal: 所有后续缩放都与此相关,我们可以正常进行:

 var svg = d3.select("svg"); var g = svg.append("g"); // define a zoom behavior: var zoom = d3.zoom() .on("zoom", zoomed); // call the zoom: svg.call(zoom) // trigger tha initial zoom with an initial transform. svg.call(zoom.transform,d3.zoomIdentity.scale(20).translate(-100,-100)); // draw the visualization: var rect = g.append("rect") .attr("width", 5) .attr("height", 5) .attr("x", 100) .attr("y", 100); // zoomed function: // zoom as normal. function zoomed() { g.attr("transform",d3.event.transform); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg width="500" height="300"></svg> 

The above snippet applies an initial zoom (scale 20, translate -100,-100) and uses this as the starting point for the zoom interaction. 上面的代码段应用了初始缩放(缩放20,平移-100,-100)并将其用作缩放交互的起点。 The comment should help explain the process. 评论应该有助于解释这个过程。

// It appears that you're moving #mainGrid and not #svg. So when you call zoom from svgElement it is zooming from it's 0,0 position. 

// Or it may because you don't have pound sign in d3.select
var svgElement = d3.select("#svg");

// Try changing svgElement to gridElement

gridELement.call(d3.zoom()
  .scaleExtent([1 / 2, 4])
  .on("zoom", zoomed));

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

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