cpz cpz - 4 years ago 233
Javascript Question

SVG Circle element jumps upon scale transform

Below is the code to have a circle and scale it on mouseover using D3. It does what it is supposed to do but also takes cricle to somewhere else, meaning circle scales and jumps(translates) to some other location. I cannot apprehend the cause for it.

this.node = this.chartLayer.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(data.nodes)
.enter().append("circle")
.attr("r", 10)
.attr("fill", (d) => { return this.colors(d.group); })
.on('mouseover', function(d) {
d3.select(this).attr('transform', 'scale(' + 2 + ')');
})

Answer Source

This has nothing to do with D3 (be it v3 or v4). The problem here is that scale is centered at the origin (0,0) of the SVG, which is the top left corner. Because of this, any element that is not on that position (0,0) will seem to move.

Have a look at this (hover over the circle):

var circle = d3.select("circle");
circle.on('mouseover', function(d) {
    d3.select(this).attr('transform', 'scale(' + 2 + ')');
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg>
	<circle cx="150" cy="75" r="20" fill="teal"></circle>
</svg>

Solution: translate the element to the origin before the scale:

var circle = d3.select("circle");
circle.on('mouseover', function(d) {
    d3.select(this).attr('transform', 'translate(-150,-75) scale(' + 2 + ')');
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg>
	<circle cx="150" cy="75" r="20" fill="teal"></circle>
</svg>

D3 Solution (way better): simply change the radius of the circle:

var circle = d3.select("circle");
circle.on('mouseover', function(d) {
    d3.select(this).attr('r', 40);
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg>
	<circle cx="150" cy="75" r="20" fill="teal"></circle>
</svg>

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download