Reputation: 53
d3 stores the transform state of an element and updates it when there is a zoom event.
I want to use my own object to store the transform state, and only use the d3 zoom event to update it.
Here's an example of what I've tried to do:
// My transform state object
myTransState = {x:0, y:0, k:1}
onZoomEvent(e){
// Update my transform state object with change
myTransState.x += e.transform.x
myTransState.y += e.transform.y
myTransState.k *= e.transform.k
// Reset d3 transform state
e.transform.x = 0
e.transform.y = 0
e.transform.k = 1
}
This isn't working. The increment in x and y grows large and the plot moves far away from the mouse pointer.
I know I can use the d3 state transform directly, however I need to track the state myself for some situations (for example, separate x and y scale factors kx and ky).
Why isn't this working as expected? Is there something else that is modifying the d3 transform state after I reset it?
Upvotes: 0
Views: 631
Reputation: 1931
Modifying the event is not enough to reset the zoom transform, because d3 does not store the current zoom coordinates in the event.
To reset the transform, you need to call the zoom.transform
selection.call(zoom.transform, zoomIdentity)
Where the selection
is the same selection that called selection.call(zoom)
, and zoomIdentity
is the identity transform {x: 0, y:0, z:1}
Be aware that calling zoom.transform
will also trigger the onZoomEvent
callback. To avoid a infinite loop, you can check if the transform of the event is {x: 0, y: 0, z: 1}
, and if it is the callback is cancelled.
onZoomEvent(e){
if(e.transform.toString() === zoomIdentity.toString()) {
return
}
// Update my transform state object with change
myTransState.x += e.transform.x
myTransState.y += e.transform.y
myTransState.k *= e.transform.k
// Reset d3 transform state
selection.call(zoom.transform, zoomIdentity)
}
Upvotes: 1