Home > Back-end >  offset-path leaving a fading trail
offset-path leaving a fading trail

Time:11-13

what do I need to include to make a white trail following it? I tried adding 10 spans and giving them the same path and delaying each one but it looked so off.

.container{
  width: 100vw;
  height: 100vh;
  background: gray;
}

.orb{
background: #00fff9;
    offset-path: path(
        "M257.004 129.794C321.128 129.794 380.697 139.056 425.611 154.622C479.727 173.378 513 201.806 513 227.548C513 254.373 477.738 284.575 419.624 303.958C375.689 318.612 317.874 326.262 257.004 326.262C194.596 326.262 135.5 319.081 91.0694 303.797C34.8572 284.455 1 253.863 1 227.548C1 202.015 32.7685 173.806 86.1237 155.079C131.206 139.257 192.246 129.794 256.996 129.794H257.004Z"
    );
    box-shadow: 0 0 10px #00fff9,
    0 0 20px #00fff9,
    0 0 30px #00fff9,
    0 0 40px #00fff9,
    0 0 50px #00fff9,
    0 0 60px #00fff9,
    0 0 70px #00fff9,
    0 0 80px #00fff9,
    0 0 90px #00fff9;
    border-radius: 50%;
    width: 20px;
    height: 20px;
    animation: move 10s linear infinite;
}

@keyframes move {
    100% { 
      offset-distance: 100%;
    }
}
<div >
  <div >
  </div>
</div>

CodePudding user response:

Here's an implementation that uses SVG <animateMotion> instead of CSS offset-path. (The path data might look a bit different, but they are basically the same.)

The trail is done with a stroke-dashoffset animation. The path gets the pathLength="100", and is then drawn ten times, each with a stroke-dasharray="2 98". That way, only a dash with a length of 2 of 100 along the path is drawn.

Then, each of the ten copies of the path gets a fading opacity, and its stroke-dashoffset is animated such that they are positioned one behind the other and moving behind the glowing orb. That part gets admitedly a bit verbose, as you need to write an individual animation rule for each of the copies. The combination of them all is then blured to smooth it.

For the orb, a custom SVG filter is used, since the drop-shadow property can't be used directly for SVG grafics.

svg {
  background-color: grey;
  overflow: visible;
  width: 100vw;
  height: 100vh;
}
.orb {
  fill: #00fff9;
}
.orb :first-child {
  filter: url(#glow);
}
.trail {
  filter: blur(4px);
}
.trail use {
  fill: none;
  stroke: white;
  stroke-width: 10;
  stroke-dasharray: 2 98;
}
.trail :nth-child(1) {
  animation: trail1 10s linear infinite;
  stroke-opacity: 0.5;
}
@keyframes trail1 {
  from {stroke-dashoffset: 2}
  to {stroke-dashoffset: -98}
}
.trail :nth-child(2) {
  animation: trail2 10s linear infinite;
  stroke-opacity: 0.45;
}
@keyframes trail2 {
  from {stroke-dashoffset: 4}
  to {stroke-dashoffset: -96}
}
.trail :nth-child(3) {
  animation: trail3 10s linear infinite;
  stroke-opacity: 0.4;
}
@keyframes trail3 {
  from {stroke-dashoffset: 6}
  to {stroke-dashoffset: -94}
}
.trail :nth-child(4) {
  animation: trail4 10s linear infinite;
  stroke-opacity: 0.35;
}
@keyframes trail4 {
  from {stroke-dashoffset: 8}
  to {stroke-dashoffset: -92}
}
.trail :nth-child(5) {
  animation: trail5 10s linear infinite;
  stroke-opacity: 0.3;
}
@keyframes trail5 {
  from {stroke-dashoffset: 10}
  to {stroke-dashoffset: -90}
}
.trail :nth-child(6) {
  animation: trail6 10s linear infinite;
  stroke-opacity: 0.25;
}
@keyframes trail6 {
  from {stroke-dashoffset: 12}
  to {stroke-dashoffset: -88}
}
.trail :nth-child(7) {
  animation: trail7 10s linear infinite;
  stroke-opacity: 0.2;
}
@keyframes trail7 {
  from {stroke-dashoffset: 14}
  to {stroke-dashoffset: -86}
}
.trail :nth-child(8) {
  animation: trail8 10s linear infinite;
  stroke-opacity: 0.15;
}
@keyframes trail8 {
  from {stroke-dashoffset: 16}
  to {stroke-dashoffset: -84}
}
.trail :nth-child(9) {
  animation: trail9 10s linear infinite;
  stroke-opacity: 0.1;
}
@keyframes trail9 {
  from {stroke-dashoffset: 18}
  to {stroke-dashoffset: -82}
}
.trail :nth-child(10) {
  animation: trail10 10s linear infinite;
  stroke-opacity: 0.05;
}
@keyframes trail10 {
  from {stroke-dashoffset: 20}
  to {stroke-dashoffset: -80}
}
<svg viewBox="-10 110 550 240">
  <defs>
    <filter id="glow" x="-1" y="-1" width="3" height="3">
      <feGaussianBlur stdDeviation="12"/><!-- defines how blured the glow is -->
      <feComponentTransfer>
        <feFuncA type="linear" slope="3"/><!-- defines how bright the glow is -->
      </feComponentTransfer>
    </filter>
    <path id="ellipse" pathLength="100" d="M257 130A256 98 0 1 1 257 326 256 98 0 1 1 257 130Z" />
  </defs>
  <g >
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
    <use href="#ellipse"/>
  </g>
  <g >
    <circle r="12"/><!-- defines how wide the glow is -->
    <circle r="10"/>
    <animateMotion dur="10s" repeatCount="indefinite">
      <mpath href="#ellipse"/>
    </animateMotion>
  </g>
</svg>

You could write the trail animation also with <animate>. It would look like this:

<use href="#ellipse">
  <animate attributeName="stroke-dashoffset"
           dur="10s" repeatCount="indefinite"
           from="2" to="-98" />
</use>

Which variant you use is a matter of taste.

  • Related