color transitions based on rgba

1,648 views
Skip to first unread message

greg

unread,
Mar 5, 2012, 7:40:48 AM3/5/12
to d3...@googlegroups.com
Hi, 

I am having my problems with color transitions based on rgba. I searched this forum and found some threads but nothing solved my problem. I just don't get smooth transitions but instead black during the transitions and finally the end state. Here is some simple code:

d3.selectAll("circle")
   .style("fill","rgba(60,179,113, 0.7)")
   .style("stroke","rgba(60,179,113, 1)")
      .transition().duration(1500)
      .style("fill","rgba(70, 130, 180, 0.7)")
      .style("stroke","rgba(70, 130, 180, 1)");

This is the simplified version. I actually define the original colors through css but that didn't work either. The best case would actually if I can define both states through css and change the class in the transition .transition().attr("class","color2"). Is that possible? 

Any ideas what's going wrong?

Thanks!

Mike Bostock

unread,
Mar 5, 2012, 7:58:35 AM3/5/12
to d3...@googlegroups.com
You need to transition fill and fill-opacity (and stroke and
stroke-opacity) separately; unless I'm mistaken, SVG does not support
rgba colors yet.

Mike

Jason Davies

unread,
Mar 5, 2012, 8:05:14 AM3/5/12
to d3...@googlegroups.com
On Mon, Mar 05, 2012 at 04:40:48AM -0800, greg wrote:
> I am having my problems with color transitions based on rgba. I searched
> this forum and found some threads but nothing solved my problem. I just
> don't get smooth transitions but instead black during the transitions and
> finally the end state. Here is some simple code:
>
> d3.selectAll("circle")
> .style("fill","rgba(60,179,113, 0.7)")
> .style("stroke","rgba(60,179,113, 1)")
> .transition().duration(1500)
> .style("fill","rgba(70, 130, 180, 0.7)")
> .style("stroke","rgba(70, 130, 180, 1)");
>
> This is the simplified version. I actually define the original colors
> through css but that didn't work either.

The problem here is that D3 is using string interpolation (because it
doesn't treat rgba() specially, unlike rgb() and #RRGGBB). The way this
works is it finds all numbers in the source/target strings, and then
interpolates matching numbers. However, this results in floating point
numbers, which is fine in most cases, but in this particular case, CSS
requires the red/green/blue components of rgba to be integers, hence
you're seeing black in the interim. I'm not sure why you're seeing it
in the end state - it seems to look okay for me.

One quick workaround would be to use rgb instead, and use fill-opacity
to set the alpha component.

In the meantime we'll probably figure out a way for D3 to handle rgba()
properly: https://github.com/mbostock/d3/issues/582

> The best case would actually if I
> can define both states through css and change the class in the transition
> .transition().attr("class","color2"). Is that possible?

This isn't possible at the moment using D3. It *might* be possible to
do by temporarily setting the target class, fetching the computed style
and then performing the interpolation, but I haven't tried this.

--
Jason Davies, http://www.jasondavies.com/

Jason Davies

unread,
Mar 5, 2012, 8:27:12 AM3/5/12
to d3...@googlegroups.com
On Mon, Mar 05, 2012 at 01:05:14PM +0000, Jason Davies wrote:
> One quick workaround would be to use rgb instead, and use fill-opacity
> to set the alpha component.

Another workaround is to use percentages instead, as decimal values are
allowed here i.e. rgba(r%, g%, b%, a).

Jason Davies

unread,
Mar 5, 2012, 8:35:21 AM3/5/12
to d3...@googlegroups.com

Ah yes, it looks like SVG only specifies CSS2, but some browsers
(WebKit, at least) appear to have added support for rgba too e.g. see
https://bugs.webkit.org/show_bug.cgi?id=16183 - so support for rgba in
SVG may vary between browsers.

d...@dddinfographic.com

unread,
May 10, 2015, 10:16:47 PM5/10/15
to d3...@googlegroups.com
Hi - I experience something similar when transitioning rgba background-color styles of a div rather than an SVG element. So when transitioning from (0,0,0,.25) to (255,0,0,.75), for example, that change happens only abruptly at the end of the duration. Should I just not? Or is there a way to make this work for non-svg elements? - D
Reply all
Reply to author
Forward
0 new messages