关于javascript:canvas多点生成平滑曲线

36次阅读

共计 2138 个字符,预计需要花费 6 分钟才能阅读完成。


<!DOCTYPE html>
<html>

<head>
    <meta charset=utf-8 />
    <title>Demo smooth connection</title>
</head>

<body>

    <canvas id="canvas"></canvas>
    <style>
        html {
            position: relative;
            height: 100%;
            width: 100%;
        }

        body {
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            margin: 0;
        }

        canvas {outline: 1px solid red;}
    </style>

    <script>


        const getDistance = (p1, p2) => {
            return Math.sqrt(Math.pow(p1.x + p2.x, 2)
                +
                Math.pow(p1.y + p1.y, 2)
            )
        }

        const getControlpoint = (points) => {// 三个点出两个控制点
            const p01 = getDistance(points[0], points[1])
            const p12 = getDistance(points[1], points[2])
            const p02 = p01 + p12
            let vector = [points[2].x - points[0].x, points[2].y - points[0].y]
            return [
                {x: points[1].x - vector[0] * 0.5 * p01 / p02,
                    y: points[1].y - vector[1] * 0.5 * p01 / p02
                },
                {x: points[1].x + vector[0] * 0.5 * p01 / p02,
                    y: points[1].y + vector[1] * 0.5 * p01 / p02
                }
            ]
        }


        let canvas = document.querySelector('canvas')
        let ctx = canvas.getContext('2d')
        window.onload = window.onresize = () => {
            canvas.width = document.body.clientWidth
            canvas.height = document.body.clientHeight
            drawBezierCurve()
            drawPoint()}
        let points = [{ x: 131, y: 193},
            {x: 187, y: 128},
            {x: 231, y: 240},
            {x: 280, y: 124},
            {x: 340, y: 236},
            {x: 368, y: 131},
            {x: 416, y: 239},

        ]
        const drawPoint = () => {
            points.forEach(point => {ctx.beginPath()
                ctx.arc(point.x, point.y, 5, 0, 2 * Math.PI)
                ctx.fill()})
        }
        const drawBezierCurve = () => {
            let len = points.length
            if (len < 2) {return}
            ctx.beginPath()
            ctx.moveTo(points[0].x, points[0].y)
            if (len === 2) {ctx.lineTo(points[1].x, points[1].y)
            } else {let controlPoint = []
                for (let i = 1; i < len - 1; i++) {controlPoint = controlPoint.concat(getControlpoint([points[i - 1], points[i], points[i + 1]]))
                }
                let i = 2
                ctx.quadraticCurveTo(controlPoint[0].x, controlPoint[0].y, points[1].x, points[1].y)
                for (; i < len - 1; i++) {
                    ctx.bezierCurveTo(controlPoint[(i - 2) * 2 + 1].x,
                        controlPoint[(i - 2) * 2 + 1].y,
                        controlPoint[(i - 1) * 2].x,
                        controlPoint[(i - 1) * 2].y,
                        points[i].x,
                        points[i].y
                    )
                }
                console.log(controlPoint, i)
                ctx.quadraticCurveTo(controlPoint[(i - 2) * 2 + 1].x,
                    controlPoint[(i - 2) * 2 + 1].y,
                    points[i].x,
                    points[i].y
                )

            }


            ctx.strokeStyle = 'blue'
            ctx.stroke()}



    </script>

</body>

</html>

留神点:1. 第二个点和最初一个点要应用 quadraticCurveTo, 2. 线 1 受 2 点和 3 点管制

参考资料:https://stackoverflow.com/questions/7054272/how-to-draw-smooth-curve-through-n-points-using-javascript-html5-canvas/10060462#10060462
原理:http://scaledinnovation.com/analytics/splines/aboutSplines.html

正文完
 0