I would like to create a blinking effect on some sectors of my pie chart that is created using d3js. The animation is incorporated by assigning the following css class to the path that represents the sector.
.blink{
animation: blinking 1s infinite;
}
@keyframes blinking {
0% { fill: red; }
50% { fill: red; }
51% { fill: white; }
100% { fill: white; }
}
This causes the sector to blink, switching between red and white every second. However, this overrides the original colour. I want to instead preserve the colour and have it switching between red and the original colour. How can I achieve that? Note that the original colour depends on the value of my chart, so I do not know what it is beforehand and cannot just replace the colour white with whatever it would be.
CodePudding user response:
If you don't mind the change being animated, all you need to do is set red
at 50%
without specifying anything else:
.blink {
animation: blinking 1s infinite;
}
@keyframes blinking {
50% { fill: red; }
}
<svg height="100" width="300">
<circle cx="50" cy="50" r="40" fill="blue"/>
<circle cx="250" cy="50" r="40" fill="green"/>
</svg>
If you want the animation jumping between values (exactly as specified in @keyframes
), it's only possible if the fill
is inherited (from whatever the direct parent resolves as fill
, using inherit
as alternative color:
.blink {
animation: blinking 1s infinite;
}
@keyframes blinking {
0% { fill: red; }
50% { fill: red; }
51% { fill: inherit; }
100% { fill: inherit; }
}
<svg height="100" width="100" fill="blue">
<circle cx="50" cy="50" r="40" fill="green" />
</svg>
However, this solution has a disadvantage. It ignores any fill
set directly on the element and animates to whatever the direct parent resolves for fill
property. In other words, if you set fill
to blue
on the element and the parent resolves to black
, it will alternate between red
and black
, ignoring blue
altogether.
In the example above green
is ignored.
Probably the only way to get exactly what you want, regardless of whether the current fill is inherited or own is by using JavaScript. Save the initial value and then animate between it and red
An alternate solution worth considering is using color
instead of fill
and setting fill
to currentColor
. This means your elements should have the color
set to a particular color, not the fill
. Here's a test:
.blink {
animation: blinking 1s infinite;
}
@keyframes blinking {
0% { fill: red; }
50% { fill: red; }
51% { fill: currentColor; }
100% { fill: currentColor; }
}
<svg height="100" width="300" style="color: blue">
<circle cx="50" cy="50" r="40" style="color: green" />
<circle cx="250" cy="50" r="40" />
</svg>
As you can see, currentColor
works for both own and inherited values. Unfortunately, there is no implementation of its fill
counterpart (e.g: currentFill
). Yet.
CodePudding user response:
You can do by just setting a single frame in your keyframe
. Like so:
.blink{
animation: blinking 1s infinite;
}
@keyframes blinking {
50% {
fill: red;
}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128" viewBox="0 0 32 32">
<path d="M30.148 5.588c-2.934-3.42-7.288-5.588-12.148-5.588-8.837 0-16 7.163-16 16s7.163 16 16 16c4.86 0 9.213-2.167 12.148-5.588l-10.148-10.412 10.148-10.412zM22 3.769c1.232 0 2.231 0.999 2.231 2.231s-0.999 2.231-2.231 2.231-2.231-0.999-2.231-2.231c0-1.232 0.999-2.231 2.231-2.231z"></path>
</svg>