在Angular中拖动时触发D3缩放事件

4

简述:拖动SVG图形会导致旋转和平移。


我正在尝试使用D3(v.4)作为Angular服务的一部分,在SVG组上实现拖动和缩放事件。

this.unitGroup = this.svg.append('g')
  .attr('id', 'unitGroup')
  .call(this.drag)
  .call(this.zoom);

拖动操作可以使SVG图形发生移动。
drag = d3.drag()
.on('start', () => {
  console.log('drag start');
  this.setClickOrigin(d3.event);
})
.on('drag', (d, i, n) => {
  const target = d3.select(n[i]).node() as any;
  const m = target.getCTM();
  const x = d3.event.x - this.clickOrigin.x;
  const y = d3.event.y - this.clickOrigin.y;
  this.setClickOrigin(d3.event);
  this.translate(target, x, y);
});

当缩放时,SVG 会旋转。

zoom = d3.zoom()
.on('zoom', (d, i, n) => {
  const target = d3.select(n[i]).node() as any;
  const m = target.getCTM();
  const b = target.getBBox();
  const dir = (d3.event.sourceEvent.deltaY > 0) ? 1 : -1;
  this.rotate(target, dir);
});

我的原始代码运行良好,但是将其集成到Angular中出现了一些问题。
当前的问题是,当您拖动 unitGroup 时,它会触发 zoom 事件和 drag 事件。
期望的行为是:
  • '单击并拖动'可以在x和y维度上平移小的深灰色框。
  • '鼠标滚轮滚动'可以使小的深灰色框围绕其中心旋转。

这里是一个Plunker:https://embed.plnkr.co/0GrGG7T79ubpjYa2ChYp/


zone@0.8.18已经发布。所以你的Plunker现在应该可以工作了。 - yurzui
1个回答

5
实际上,你在这里看到的是预期行为。
在D3中,d3.zoom()不仅处理缩放,还处理平移。因此,mousemove事件既被d3.drag()处理,也被缩放函数处理。
正如Bostock(D3创建者)曾经说过的:
结合这两种行为*意味着手势解释是模糊的,并且高度敏感于位置。(*缩放和拖动)
我能想到的最简单的解决方案就是,在缩放函数中检查你是否有“真正”的缩放(鼠标滚轮),如果没有(没有鼠标滚轮),返回:
if(!d3.event.sourceEvent.deltaY) return;

这是您的 plunker,只有这个更改:https://plnkr.co/edit/jz5X4Vm9wIzbKmTQLBAT?p=preview


2
确实,在d3.js库中有stopImmediatePropagation()。但是Angular在处理它时存在一些问题 https://github.com/angular/angular/pull/19222 这也是zone js的问题。例如,让我们看看这个例子https://jsfiddle.net/hv5tLx9L/ 然后包含zonejs https://jsfiddle.net/08jzzjd5/ - yurzui
2
提交 https://github.com/angular/zone.js/commit/dcc285aab37bdd90b6d7133fc73045100861c61c 已合并,也许只需等待 zonejs 的新版本即可。 - yurzui
1
谢谢。由于我的解决方案使用 d3.event.sourceEvent.deltaY 工作,我刚刚删除了对 stopPropagation 的提及。 - Gerardo Furtado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接