1

Recently, some readers added me to WeChat to inquire about this issue:
image.png

The effect is a polyline path animation effect, as shown in the following figure:
动画.gif

To achieve the above path animation, you can generally use the animation function of svg. Or use canvas to draw, combined with path mathematical calculation to achieve.

If you use canvas to draw, the difficulty lies in:

  • Need to calculate the sub-path, this calculation is more complicated. (Of course it can be achieved)
  • Gradient calculation, as can be seen from the figure, the sub-path of the animation has a gradual effect, and it is also very complicated to calculate the gradient in sections.

This article introduces a way of thinking, using the clip method to dynamically move the clip area to achieve an approximate effect. How to do it in detail.

Draw gray path

The code for drawing the path is relatively simple, so I won’t explain it in detail here. The following code simulates the drawing of a polyline path:

 ctx.beginPath();    
 ctx.moveTo(100,100);
 ctx.lineTo(200,100);
 ctx.lineTo(230,200);
 ctx.lineTo(250,50);
 ctx.lineTo(270,180);
 ctx.lineTo(300,60);
 ctx.lineTo(330,160);
 ctx.lineTo(350,60);
 ctx.lineTo(380,100);
 ctx.lineTo(480,100);
 ctx.strokeStyle = "gray";
 ctx.lineJoin = "round";
 ctx.stroke(); 

The effect is as follows:

gray

Draw a bright path

The code for drawing a bright path is the same as the code for drawing a gray path, except that the style is a bright color:

ctx.save();
            ctx.beginPath();    
            ctx.moveTo(100,100);
            ctx.lineTo(200,100);
            ctx.lineTo(230,200);
            ctx.lineTo(250,50);
            ctx.lineTo(270,180);
            ctx.lineTo(300,60);
            ctx.lineTo(330,160);
            ctx.lineTo(350,60);
            ctx.lineTo(380,100);
            ctx.lineTo(480,100);
            ctx.strokeStyle = "gray";
            ctx.lineJoin = "round";
            ctx.stroke(); 

The effect is as follows:
bright

clip controls the drawing area of the bright path

The clip method of canvas can control the drawing area. Through this method, you can control a part of the smart drawing path:

        ctx.beginPath();
        ctx.rect(offset,0,100,500); // offset 等于0
        ctx.clip();
           ...
        ctx.stroke(); 

After clip, only a part of the bright color path will be drawn, as shown in the following figure:
clip

Animation effect

By constantly changing the value of offset, the effect of moving the bright color path of the road can be achieved. The code is as follows:

 offset += 2;
 if(offset > 600){
       offset = 100;
 }
requestAnimationFrame(animate);

The final effect is as follows:

动画1.gif

Gradient

We know that the gradient cannot follow any path. If you calculate the polyline, it is very troublesome to calculate the gradient in sections. In fact, in this case, although it is a polyline, the overall direction of movement is always from left to right, so the gradual change from left to right can be used to approximate the simulation:

function createGradient(ctx,x0,y0,x1,y1){
          var grd = ctx.createLinearGradient(x0,y0,x1,y1);
           grd.addColorStop(0,'#129ab3');
           grd.addColorStop(1,"#19b5fe");
           return grd;
}

ctx.strokeStyle = createGradient(ctx,offset,0,offset + 100,0);

The final effect is as follows:

动画2.gif

All codes

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>line animate</title>
    <style>
        canvas {
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="600" height="400"></canvas>
    <script>
        var ctx = document.getElementById( 'canvas' ).getContext( '2d' );
        var w = canvas.width,
                h = canvas.height;

        var x = w / 2,y = h / 2;

        function setupCanvas(canvas) {
            let width = canvas.width,
            height = canvas.height,
            dpr = window.devicePixelRatio || 1.0;
            if (dpr != 1.0 ) {
            canvas.style.width = width + "px";
            canvas.style.height = height + "px";
            canvas.height = height * dpr;
            canvas.width = width * dpr;
            ctx.scale(dpr, dpr);
            }
        }
        setupCanvas(canvas);
        var offset = 100;
        function createGradient(ctx,x0,y0,x1,y1){
           var grd = ctx.createLinearGradient(x0,y0,x1,y1);
           grd.addColorStop(0,'#9a12b3');
           grd.addColorStop(1,"#19b5fe");
           return grd;
        }

        function animate(){
            ctx.fillStyle = "black";
            ctx.fillRect(0,0,canvas.width,canvas.height);
            ctx.lineWidth = 3;
            ctx.save();
            ctx.beginPath();    
            ctx.moveTo(100,100);
            ctx.lineTo(200,100);
            ctx.lineTo(230,200);
            ctx.lineTo(250,50);
            ctx.lineTo(270,180);
            ctx.lineTo(300,60);
            ctx.lineTo(330,160);
            ctx.lineTo(350,60);
            ctx.lineTo(380,100);
            ctx.lineTo(480,100);
            ctx.strokeStyle = "gray";
            ctx.lineJoin = "round";
            ctx.stroke(); 

            ctx.beginPath();
            ctx.rect(offset,0,150,500);
            ctx.clip();
            ctx.beginPath();
            ctx.moveTo(100,100);
            ctx.lineTo(200,100);
            ctx.lineTo(230,200);
            ctx.lineTo(250,50);
            ctx.lineTo(270,180);
            ctx.lineTo(300,60);
            ctx.lineTo(330,160);
            ctx.lineTo(350,60);
            ctx.lineTo(380,100);
            ctx.lineTo(480,100);
            ctx.lineWidth = 4;
            ctx.strokeStyle = createGradient(ctx,offset,0,offset + 150,0);
            ctx.lineCap = "round";
            // ctx.globalCompositeOperation = 'lighter';
            ctx.lineJoin = "round";
            ctx.stroke(); 

            ctx.restore();

            offset += 2;
            if(offset > 600){
                offset = 100;
            }

            requestAnimationFrame(animate);
        }

        animate();
    </script>
</body>
</html>

to sum up

In fact, the overall idea is to use approximation, rather than strictly control the path length and gradual effect, so that the above functions can be realized more conveniently. In fact, sometimes the human eye can’t distinguish some details and visualize it. Sometimes it can only make people “feel” that way. In fact, the goal is achieved.

The above scheme can only be applied, the overall direction of the polyline path is the same. If the overall direction is first horizontally to the right and then vertically downwards, or even turning back, it is not suitable.

Follow the public account "ITMan Biaoshu" to receive more valuable articles in time. In addition, if you are interested in visualization, you can communicate with me on WeChat 541002349.


netcy
204 声望120 粉丝

欢迎对canvas、webgl、图形学感兴趣的读者订阅专栏。


引用和评论

0 条评论