Mateus Silva
Mateus Silva

Reputation: 826

Curve rectangle to follow a path

It is possible with divs, shapes or svgs to curve an item to follow the curve of the path.

It's just an example, but imagine the rectangles curving on the edges, right now it's just had turn 90deg from one frame to another

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">      <title>frame</title><style>
        main {
          width: 100vw;height: 100vh;position: absolute;
        }
        div {
          display: none;position: absolute;will-change: offset-distance;width: 200px;
          height: 40px;background: hsl(313,100%,50%);offset-anchor: top;
          offset-rotate: auto;offset-path: path('M 0 0 L 600 0 L 600 400 L 0 400 L 0 0'); 
        }
        
        div:nth-of-type(4n+2) {background: hsl(343,100%,50%)}
        div:nth-of-type(4n+3) {background: hsl(13,100%,50%)}
        div:nth-of-type(4n+4) {background: rgb(37, 16, 226)}
        body {margin: 0;padding: 0;}            
        svg, aside {    display: none;}
        div {    display: block;    }
        * {box-sizing: border-box;}         
        
        </style>
</head>    <body>    <main><div></div>      <div></div>     <div></div>     <div></div>     <div></div><div></div>    </main>
<script>
    var rateRange = document.getElementById('playback-rate');
    var shapers = [].slice.call(document.querySelectorAll('div'));
    var DURATION = 200000;
    var animations = [];

    shapers.forEach(function(s, i) {
        var animation = s.animate([
        {offsetDistance: 0},
        {offsetDistance: '100%'}
        ], {
            duration: DURATION,
            delay: -i / shapers.length * DURATION,
            iterations: Infinity
        });
        animations.push(animation);
    });
</script>
</body>
</html>

Upvotes: 4

Views: 118

Answers (1)

enxaneta
enxaneta

Reputation: 33044

This is an svg solution. I'm using 4 overlapping paths where the stroke-dasharray is like this: stroke-dasharray: 2 2 2 2 2 2 2 2 2 242 If you are summing the dashes and the gaps the total is 260.

Also stroke-linecap: round When the dashes are very near one of the other stroke-linecap: round make them overlapping giving the apparence of a continuos line.

The total length of the path is also 260. I'm animating the stroke.dashoffset property of the path.

path {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  stroke-dasharray: 2 2 2 2 2 2 2 2 2 242;
  animation: dash 5s linear infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: -260;
  }
}
<svg viewBox="0 0 100 70" >

  <path id="pth" stroke="red" d="M10,10L90,10L90,60L10,60z" />

  <path stroke="blue" d="M70,10L90,10L90,60L10,60L10,10z" />

  <path stroke="green" d="M90,60L10,60L10,10L90,10z" />

  <path stroke="orange" d="M30,60L10,60L10,10L90,10L90,60z" />

</svg>

UPDATE

In order to avoid the flickering at the corners I'm changing the rectangular paths to paths with rounded corners. T make it clear what I mean by this I'm adding an extra path: the #track.

path {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  stroke-dasharray: 2 2 2 2 2 2 2 2 2 225;
  animation: dash 5s linear infinite;
}

#track {
  stroke-width: 1;
  stroke-dasharray: 245 0;
}

@keyframes dash {
  to {
    stroke-dashoffset: -245;
  }
}

svg {
  width: 300px;
}
<svg viewBox="0 0 100 70">

  <path id="pth" stroke="red" d="M27.000,10.000 Q37,10 47.000,10.000L80.000,10.000 Q90,10 90.000,20.000L90.000,50.000 Q90,60 80.000,60.000L20.000,60.000 Q10,60 10.000,50.000L10.000,20.000 Q10,10 20.000,10.000Z" />

  <path stroke="blue" d="M90.000,27.000 Q90,37 90.000,47.000L90.000,50.000 Q90,60 80.000,60.000L20.000,60.000 Q10,60 10.000,50.000L10.000,20.000 Q10,10 20.000,10.000L80.000,10.000 Q90,10 90.000,20.000Z" />


  <path stroke="green" d="M73.000,60.000 Q63,60 53.000,60.000L20.000,60.000 Q10,60 10.000,50.000L10.000,20.000 Q10,10 20.000,10.000L80.000,10.000 Q90,10 90.000,20.000L90.000,50.000 Q90,60 80.000,60.000Z" />

  <path stroke="orange" d="M10.000,45.000 Q10,35 10.000,25.000L10.000,20.000 Q10,10 20.000,10.000L80.000,10.000 Q90,10 90.000,20.000L90.000,50.000 Q90,60 80.000,60.000L20.000,60.000 Q10,60 10.000,50.000Z" />
  
  
  <path id="track" d="M90.000,27.000 Q90,37 90.000,47.000L90.000,50.000 Q90,60 80.000,60.000L20.000,60.000 Q10,60 10.000,50.000L10.000,20.000 Q10,10 20.000,10.000L80.000,10.000 Q90,10 90.000,20.000Z" stroke="black" />

</svg>

Upvotes: 4

Related Questions