欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Canvas 画贝塞尔曲线(二阶曲线和三阶曲线)

程序员文章站 2022-04-25 11:45:05
...

效果图为动态图,一个小圆点沿着曲线运动,并显示实时点坐标。

在线预览:

二阶:http://qingshanboke.com/demo/quadratic.htm

三阶:http://qingshanboke.com/demo/bezier.htm

 

一、实现思路:

1.用两个canvas实现,一个绘制曲线,一个绘制运动圆点。

2.绘制曲线:可以通过canvas提供的API方法绘制。

二阶:quadraticCurveTo(controlX, controlY, endingPointX, endingPointY) 1个控制点。

三阶:bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endPointX, endPointY),2个控制点。

3.绘制圆点:根据贝塞尔曲线公式,计算出不同时刻圆点坐标,然后绘制到canvas上。

二、实现过程:

1.二阶曲线:

Canvas 画贝塞尔曲线(二阶曲线和三阶曲线)

核心公式:Canvas 画贝塞尔曲线(二阶曲线和三阶曲线)

实现代码:

<html>
<title>二阶贝塞尔曲线</title>
<style type="text/css">
    body {
        background: black;
    }
    
    #canvas {
        position: absolute;
        top: 0;
        left: 0;
        width: 600px;
        height: 600px;
    }
    
    #line {
        position: absolute;
        top: 0;
        left: 0;
        width: 600px;
        height: 600px;
    }
</style>

<body>
    <canvas id="canvas" width="600" height="600"></canvas>
    <canvas id="line" width="600" height="600"></canvas>
    <script type="text/javascript">
        var point = {
            begin: {
                x: 20,
                y: 20
            },
            control: {
                x: 40,
                y: 400
            },
            end: {
                x: 600,
                y: 600
            },
        };

        function drawline() {
            let canvas = document.getElementById("canvas");
            let ctx = canvas.getContext("2d");
            ctx.beginPath();

            ctx.moveTo(point.begin.x, point.begin.y);
            ctx.quadraticCurveTo(point.control.x, point.control.y, point.end.x, point.end.y);

            ctx.strokeStyle = "#2578b0";
            ctx.lineWidth = 2;
            ctx.stroke();

        }
        drawline();

        let t = 0;

        function drawPoint() {
            //根据二次贝塞尔曲线的公式,获取某时刻t[0-1]的贝塞尔曲线上的点            
            let x = Math.pow((1 - t), 2) * point.begin.x + 2 * t * (1 - t) * point.control.x + Math.pow(t, 2) * point.end.x;
            let y = Math.pow((1 - t), 2) * point.begin.y + 2 * t * (1 - t) * point.control.y + Math.pow(t, 2) * point.end.y;

            //移出画布后,重新开始
            if (x > 600) {
                t = 0;
                x = point.begin.x;
                y = point.begin.y;
            }

            let canvas = document.getElementById("line");
            let ctx = canvas.getContext("2d");

            //清除上一次的点
            ctx.clearRect(0, 0, 600, 600);
            ctx.beginPath();

            //画小圆点
            ctx.moveTo(point.begin.x, point.begin.y);
            ctx.arc(x, y, 4, 0, 2 * Math.PI, false);
            ctx.fillStyle = "white";
            ctx.fill();

            //显示坐标
            ctx.font = 'bold 12px Arial';
            ctx.textAlign = 'left';
            ctx.textBaseline = 'bottom';
            ctx.fillStyle = 'white';
            ctx.fillText("x:" + parseInt(x), x, y - 24);
            ctx.fillText("y:" + parseInt(y), x, y - 12);
            ctx.closePath();
            t += 0.006;
        }

        setInterval(drawPoint, 60);
    </script>
</body>

</html>

在线预览:http://qingshanboke.com/demo/quadratic.htm

2.三阶曲线:

Canvas 画贝塞尔曲线(二阶曲线和三阶曲线)

核心公式:Canvas 画贝塞尔曲线(二阶曲线和三阶曲线)

实现代码:

<html>
<title>三阶贝塞尔曲线</title>
<style type="text/css">
    body {
        background: black;
    }
    
    #canvas {
        position: absolute;
        top: 0;
        left: 0;
        width: 600px;
        height: 600px;
    }
    
    #line {
        position: absolute;
        top: 0;
        left: 0;
        width: 600px;
        height: 600px;
    }
</style>

<body>
    <canvas id="canvas" width="600" height="600"></canvas>
    <canvas id="line" width="600" height="600"></canvas>
    <script type="text/javascript">
        var point = {
            begin: {
                x: 0,
                y: 600
            },
            control1: {
                x: 500,
                y: 500
            },
            control2: {
                x: 400,
                y: 40
            },
            end: {
                x: 600,
                y: 0
            },
        };

        function drawline() {
            let canvas = document.getElementById("canvas");
            let ctx = canvas.getContext("2d");
            ctx.beginPath();

            ctx.moveTo(point.begin.x, point.begin.y);
            ctx.bezierCurveTo(point.control1.x, point.control1.y, point.control2.x, point.control2.y, point.end.x, point.end.y);
            ctx.strokeStyle = "#2578b0";
            ctx.lineWidth = 2;
            ctx.stroke();

        }
        drawline();

        let t = 0;

        function drawPoint() {
            //根据三次贝塞尔曲线的公式,获取某时刻t[0-1]的贝塞尔曲线上的点            
            let x = point.begin.x * Math.pow((1 - t), 3) + 3 * t * point.control1.x * Math.pow((1 - t), 2) + 3 * point.control2.x * Math.pow(t, 2) * (1 - t) + point.end.x * Math.pow(t, 3);
            let y = point.begin.y * Math.pow((1 - t), 3) + 3 * t * point.control1.y * Math.pow((1 - t), 2) + 3 * point.control2.y * Math.pow(t, 2) * (1 - t) + point.end.y * Math.pow(t, 3);

            //移出画布后,重新开始
            if (x > 600) {
                t = 0;
                x = point.begin.x;
                y = point.begin.y;
            }

            let canvas = document.getElementById("line");
            let ctx = canvas.getContext("2d");

            //清除上一次的点
            ctx.clearRect(0, 0, 600, 600);
            ctx.beginPath();

            //画小圆点
            ctx.moveTo(point.begin.x, point.begin.y);
            ctx.arc(x, y, 4, 0, 2 * Math.PI, false);
            ctx.fillStyle = "white";
            ctx.fill();

            //显示坐标
            ctx.font = 'bold 12px Arial';
            ctx.textAlign = 'left';
            ctx.textBaseline = 'bottom';
            ctx.fillStyle = 'white';
            ctx.fillText("x:" + parseInt(x), x, y - 24);
            ctx.fillText("y:" + parseInt(y), x, y - 12);
            ctx.closePath();
            t += 0.006;
        }

        setInterval(drawPoint, 60);
    </script>
</body>

</html>

在线预览:http://qingshanboke.com/demo/bezier.htm

 

参考资料:

https://www.w3school.com.cn/tags/canvas_quadraticcurveto.asp

https://www.w3school.com.cn/tags/canvas_beziercurveto.asp

https://baike.baidu.com/item/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF/1091769?fr=aladdin

https://blog.csdn.net/ixygj197875/article/details/80043658

 

相关标签: Demo