简体   繁体   中英

offset-path leaving a fading trail

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 class="container"> <div class="orb"> </div> </div>

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 class="trail"> <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 class="orb"> <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.

Edit: Generalization

The above code depends on a linear movement of the orb along the path. How would you solve this with different easings? I started to explore that and found the only realistic approach is to draw the trail frame-by-frame from Javascript. An example can be found in this Codepen .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM