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

sak*_*ret 1 javascript svg d3.js

我试图在将 SVG 元素转换为 Matrix 后放大它,但是当我开始初始缩放时,SVG 的位置重置为 0,0。我希望缩放和平移从页面加载时移动的位置开始。

<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>
Run Code Online (Sandbox Code Playgroud)

“mainGrid”SVG 元素可以很好地缩放和平移,但在第一次缩放鼠标单击或滚轮滚动期间,它会回到它的 0,0 位置(浏览器的左上角),而不是从 myMatrix 设置的转换位置进行缩放和平移。我怎样才能让 d3.event.transform 从这个偏移量开始缩放?

And*_*eid 6

问题:

d3 缩放行为不会跟踪或了解您对元素应用的变换。它被初始化为 scale 等于 1,translate 等于 0,0。所以,当你使用

gridELement.attr("transform", d3.event.transform);
Run Code Online (Sandbox Code Playgroud)

在您的缩放功能中,您是相对于这个初始比例缩放和平移。

基本原理

并非每个 d3 zoom 都操纵它调用的 SVG 元素的变换:您可能希望在绘图上的任何地方都有缩放交互,但只缩放绘图区域而不是边距。许多 d3 缩放不操作任何 SVG 变换:它们可能使用语义缩放,或者缩放可能会改变画布而不是 SVG 等。因此,d3-zoom 行为独立于元素上的任何 SVG transorm 属性( s) 它被调用。

解决方案

如果您通过操作 SVG 元素的 transform 属性进行缩放,让 D3 zoom 完成所有操作 - 无需手动操作并进行缩放,这就是缩放失步的原因。

所以,

您可以在渲染任何内容之前以编程方式触发缩放事件。最简单的方法是使用:

selection.call(zoom.transform, d3.zoomIdentity.translate(x,y).scale(k));
Run Code Online (Sandbox Code Playgroud)

此行触发缩放事件。我们可以在渲染任何东西之前使用它,并依靠 zoomed 函数来设置 SVG 变换属性的初始值。所有后续缩放都将与此相关,我们可以照常进行:

gridELement.attr("transform", d3.event.transform);
Run Code Online (Sandbox Code Playgroud)
selection.call(zoom.transform, d3.zoomIdentity.translate(x,y).scale(k));
Run Code Online (Sandbox Code Playgroud)

上面的代码段应用了初始缩放(缩放 20,平移 -100,-100)并将其用作缩放交互的起点。注释应有助于解释该过程。