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