d3-transition icon indicating copy to clipboard operation
d3-transition copied to clipboard

Opacity transition does not work properly for % values

Open matthew-h-wang opened this issue 2 years ago • 2 comments

When using transitions with the opacity style, values given in "%" units do not correctly transition from the prior value, but instead always transition from "0%". By contrast, using numbers for opacity values do correctly transition between opacity values.

Here's a simple example, where the intended effect is 5 circles who smoothly change to random opacities every update:

let data = [];

//Produce 5 points with increasing x values and random o values in range [0,100)
function updateData() {
	data = [];
	for(let i=0; i<5; i++) {
		data.push({x: i * 100 + 50, o: Math.floor(Math.random() * 100)});
	}
}

function update() {
	d3.select('svg')
	.selectAll('circle')
		.data(data)
		.join('circle')
		.attr('cy', 50)
		.attr('r', 40)
		.attr('cx', (d) => d.x)
		.transition()
		.duration(500)
		.style('opacity', (d) => d.o +"%"); // using percent units
}

function updateAll() {
	updateData();
	update();
}

updateAll();

The actual resulting effect is each update, the circles fade in from 0 opacity, rather than smoothly from the prior opacity value:

https://github.com/d3/d3/assets/7028714/c3b9a9c4-f1ac-41d4-8ff6-9ff1fcddeace

By changing the final line in update() to this:

		.style('opacity', (d) => d.o * 0.01); // using decimal units

we get the intended effect:

https://github.com/d3/d3/assets/7028714/f44aefd8-4b24-4622-bee5-3d76bfb70125

I have not tested transitioning other style properties that use percent units, but it is possible this is an issue beyond just opacity.

matthew-h-wang avatar Feb 01 '24 14:02 matthew-h-wang

I think this probably isn’t fixable and is the same fundamental issue as https://github.com/d3/d3-transition/issues/72#issuecomment-319202005 which is that transition.style depends on the computed value of the style property. In the case of opacity, the computed value is a number between 0 and 1. So you always need to specify the target value of the transition in the same manner as the computed value for the default interpolator to work correctly.

mbostock avatar Feb 01 '24 15:02 mbostock

After reading the documentation for transition.style, that makes more sense. It does feel like an easy pitfall that others might run into because many style properties work just fine with alternative units when transitions are not involved. Perhaps the docs could include some warnings/guidelines on what units are appropriate for certain common style properties.

matthew-h-wang avatar Feb 02 '24 14:02 matthew-h-wang