Home > Enterprise >  Use keyframes animation to blink but also preserve original colour
Use keyframes animation to blink but also preserve original colour

Time:09-14

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>

  • Related