Reputation: 2174
What I set for transforming <g>
is
const svg = d3.select('target-svg')
const g = d3.select('target-g')
svg.call(d3.zoom().on('zoom', () => {
g.attr('transform', d3.event.transform)
})
Now, I am trying to set transform attribute of <g>
svg tag using following sample javascript code.
g.attr('transform', 'translate(100, 100) scale(1)')
The issue is that the <g>
tag is transleted fine but when zoom in and out using mouse wheel, the <g>
is translated to origin position.
For example, if the origin coordinate of translate of <g>
is (0, 0) and I translate it to (100, 100), the <g>
's (x, y) is located (100, 100). But when I zoom it, the <g>
is go back to (0, 0).
How can I stop it?
Upvotes: 1
Views: 1371
Reputation: 38231
A D3 zoom behavior does not track an element's transform attribute - afterall, a zoom behavior might not alter it (zooming on canvas, changing color or shape on zoom, granularity of data, applying a zoom to different elements rather than the one triggering events, etc).
When you apply a transform with d3.event.transform
you are applying the current zoom transform, which starts with a translate of [0,0]
and a scale of 1
. In other words, unless you specify otherwise, the default initial zoom event with a d3 zoom behavior will always be relative to this initial state. This is why the zoom is not relative to the manually set element's transform value.
To unify a manually set transform attribute and the zoom behavior's transform, use the zoom to manage both. You can manually set the transform attribute of the g
with the zoom behavior:
var transform = d3.zoomIdentity.translate([100,100]).scale(1);
svg.call(zoom.transform, transform);
The first line manipulates a d3 zoom identity to create a new transform. The second line applies it, calling a zoom event in the process, which triggers a zoom.on event.
With this approach the zoom manages both the use of manual transform and event based transforms, so that the zoom is never out of date or "unaware" of what transform is currently applied to a selection.
Altogether, this might look like:
var svg = d3.select('body')
.append('svg')
.attr('width',500)
.attr('height',400)
var g = svg.append('g');
var rect = g.append('rect')
.attr('x', 750)
.attr('y', 100)
.attr('height',50)
.attr('width',50);
var zoom = d3.zoom()
.on('zoom', function() {
g.attr('transform',d3.event.transform);
})
var initialTransform = d3.zoomIdentity
.translate(-700,-40)
svg.call(zoom);
svg.call(zoom.transform,initialTransform);
<script src="https://d3js.org/d3.v5.min.js"></script>
Upvotes: 1