D3添加缩放和平移

问题描述 投票:1回答:1

我需要缩放和平移一组svg元素,如下例所示:

https://embed.plnkr.co/kVw0rWMo728dmbm8EjuG/

我已经完成了缩放行为,但是当我拖动鼠标(平移)时,我无法移动图形。我尝试过:

var zoom = d3.zoom()
  .scaleExtent([1, 100])
  .translateExtent([[150, 150],[150, 150]])
  .on('zoom', zoomFn);

  d3.select('svg')
  .select('g')
  .style("transform-origin", "50% 50% 0");

function zoomFn() {
  d3.select('svg').select('g')
    .style('transform', 'translate(' + d3.event.translate + ')' + ' scale(' + d3.event.transform.k + ')');
}

d3.select('svg')
  .select('rect')
  .call(zoom);

我如何在该示例中添加pan行为?

d3.js zoom pan
1个回答
1
投票

有几件事:

第一

d3.event.translate不保存变换x和y值,使用d3.event.transform获取这些值。变换对象具有x,y和k属性。

第二

如果使用.style()放置变换,则需要指定单位是偏移的像素:

var t = d3.event.transform;
d3.select("zoomedElement")
  .style('transform', 'translate('+t.x+"px,"+t.y + 'px)scale(' + t.k + ')');

或者,您可以在没有.attr()的情况下使用px

var t = d3.event.transform;
d3.select("zoomedElement")
  .style('transform', 'translate('+[t.x,t.y]+')scale(' + t.k + ')');

让我们看看你的那些变化(并没有翻译范围):

var zoom = d3.zoom()
  .scaleExtent([1, 100])
  .on('zoom', zoomFn);

  d3.select('svg')
  .select('g')
  .style("transform-origin", "50% 50% 0");

function zoomFn() {
   var t = d3.event.transform;
  d3.select('svg').select('g')
    .style('transform', 'translate('+t.x+"px,"+t.y + 'px)scale(' + t.k + ')');


}

d3.select('svg')
  .select('rect')
  .call(zoom);
    .zoom-layer {
      fill: #EEE;
      fill-opacity: 0.25;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.0.0/d3.min.js"></script>
<svg width="300" height="300">
    <g>
      <circle cx=150 cy=150 r=20 style="fill:#F22"></circle>
      <rect x=0 y=0 width=300 height=300 class="zoom-layer"></rect>
    </g>
  </svg>

您可能希望进行不包含矩形的选择 - 这应该保持不变,以便整个SVG表面保持交互

第三

看起来好像你想要一个翻译范围,有时设置有点棘手。 This的答案在缩放范围/翻译范围上有更深入的解释,但我将讨论如何将您的圆圈限制在屏幕上:

翻译为[0,0]时,您的圆圈位于svg的中间。如果我们翻译[-150,-150],你的圆圈就在svg的左上角。如果圆圈以cx = 150 cy = 150为中心,那么可视区域的左上角现在为[150,150]。因此,右下角是[450,450]。可见范围是:[[150,150],[450,450]]

翻译为[150,150]时,您的圆圈位于SVG的右下角。因为圆仍然在[150,150],所以右下角位于[150,150](这无助于清晰度,即平移和圆位置在此处具有相同的值)。左上角是[-150,-150]。可视范围必须是:[[-150,-150],[150,150]]

我们从可查看的范围限制中取出极值,因为这是保持圆形视图的转换范围:

var translateExtent = [[-150,-150],[450,450]]

当然,如果你有各个角落的东西而不是中间的东西,你会有更大的范围。

我们可以将所有内容应用到代码段:

var zoom = d3.zoom()
  .scaleExtent([1, 100])
  .translateExtent([[-150,-150],[450, 450]])
  .on('zoom', zoomFn);

  d3.select('svg')
  .select('g')
  .style("transform-origin", "50% 50% 0");

function zoomFn() {
   var t = d3.event.transform;
  d3.select('svg').select('g')
    .style('transform', 'translate('+t.x+"px,"+t.y + 'px)scale(' + t.k + ')');

  console.log(t.x,t.y)

}

d3.select('svg')
  .select('rect')
  .call(zoom);
    
    .zoom-layer {
      fill: #aaa;
      fill-opacity: 0.25;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="300" height="300">
    <g>
      <circle cx=150 cy=150 r=20 style="fill:#F22"></circle>
    </g>
    <rect x=0 y=0 width=300 height=300 class="zoom-layer"></rect>
  </svg>
© www.soinside.com 2019 - 2024. All rights reserved.