d3js javascript angular d3.js svg

javascript - d3js - Evento de zoom D3 disparando en arrastre en Angular



d3js angular (1)

Tldr; arrastrando el SVG hace que gire y traduzca.

Estoy intentando implementar eventos de arrastrar y aplicar zoom en un grupo SVG usando D3 (v.4) como parte de un servicio angular.

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

Arrastrar traduce el 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); });

Mientras el zoom gira el 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); });

Mi código original funcionó bien. Sin embargo, integrarlo en Angular ha generado algunos problemas.

El problema actual es que cuando arrastra unitGroup , desencadena el evento de zoom junto con el evento de drag .

El comportamiento esperado es que:

  • ''hacer clic y arrastrar'' traduce la caja pequeña de color gris oscuro en las dimensiones xey.
  • ''mouse-wheel-scroll'' gira la pequeña caja gris oscuro alrededor de su centro.

Aquí hay un Plunker: https://embed.plnkr.co/0GrGG7T79ubpjYa2ChYp/


En realidad, lo que estás viendo aquí es el comportamiento esperado.

En D3, d3.zoom() maneja no solo el zoom sino también el panorama. Entonces, el mousemove está siendo manejado por d3.drag() y por la función de zoom también.

Como Bostock (creador de D3) dijo una vez:

combinar estos dos comportamientos * significa que la interpretación de gestos es ambigua y altamente sensible a la posición. (* zoom y arrastre)

De repente, la solución más simple es simplemente verificar si tienes un zoom "real" (rueda del mouse) en la función de zoom y, si no lo hiciste (sin una rueda del mouse), regresa:

if(!d3.event.sourceEvent.deltaY) return;

Aquí está su plunker con ese cambio solamente: https://plnkr.co/edit/jz5X4Vm9wIzbKmTQLBAT?p=preview