如何偏移d3变焦的初始开始位置?

时间:2019-07-19 20:44:15

标签: javascript d3.js svg

在转换Matrix之后,我试图放大SVG元素,但是当我开始初始缩放时,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>

“ mainGrid” SVG元素可以缩放和平移,但在第一次单击鼠标或滚轮滚动时,它会捕捉回到其0,0位置(浏览器左上方),而不是从设置的变换位置进行缩放和平移通过myMatrix。如何获取d3.event.transform从此偏移量开始缩放?

2 个答案:

答案 0 :(得分:3)

问题:

d3缩放行为无法跟踪或不知道您对元素应用了哪些变换。它用等于1的小数位进行初始化并等于0,0的平移。因此,当您使用

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

在缩放功能中,您正在相对于此初始比例进行缩放并进行平移。

理论上

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

解决方案

如果通过操作SVG元素的transform属性进行缩放,则让D3缩放执行所有操作-无需手动操作并进行缩放,这就是缩放失去步调的方式。

所以

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

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

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

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>

以上代码段应用了初始缩放(比例尺20,转换为-100,-100),并将其用作缩放交互的起点。该评论应有助于解释该过程。

答案 1 :(得分:0)

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