当前位置: 代码网 > it编程>编程语言>Javascript > 使用JavaScript实现小球按照贝塞尔曲线运动

使用JavaScript实现小球按照贝塞尔曲线运动

2024年11月26日 Javascript 我要评论
介绍要在 javascript 中实现一个按照贝塞尔曲线运动的小球,关键是要掌握贝塞尔公式的基本原理和实现方式,以及使用 javascript 处理动画和物理运算。以下是实现的核心步骤:构建 html

介绍

要在 javascript 中实现一个按照贝塞尔曲线运动的小球,关键是要掌握贝塞尔公式的基本原理和实现方式,以及使用 javascript 处理动画和物理运算。

以下是实现的核心步骤:

  • 构建 html

  • 绘制小球。

  • 实现贝塞尔曲线路径。

  • 实现动画循环。

接下来,我们将详细介绍这些步骤。

构建 html

首先,我们需要构建一个简单的 html 文件,用于绘制我们的动画。

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>canvas</title>
    <style>
        body {
            font-family: arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
        }
        canvas {
            border-radius: 15px;
            background-color: #ffffff;
        }
    </style>
</head>
<body>
    <canvas id="demo-canvas" width="800" height="600"></canvas>

    <script>
    </script>
</body>
</html>

代码足够简单就行,我们只需要一个 canvas 元素即可。

绘制小球

接下来,我们需要在 javascript 中获取 canvas 元素,并使用 canvas 的 api 来绘制一个小球。

const canvas = document.getelementbyid('demo-canvas');
const ctx = canvas.getcontext('2d');

const ball = {
    radius: 20,
    color: '#ff0000',
};

function drawball(x, y) {
    ctx.beginpath();
    ctx.arc(x, y, ball.radius, 0, math.pi * 2);
    ctx.fillstyle = ball.color;
    ctx.fill();
}

由于我们需要让小球沿着贝塞尔曲线运动,所以在调用 drawball 函数时,需要传递最新的坐标位置,因此我们需要给 drawball 传递 x 和 y 两个参数。

贝塞尔公式

关于贝塞尔公式,网上讲解的文章博客多如牛毛,这里就不赘述了,直接上结论。

实现贝塞尔曲线路径

接下来,我们来实现 nn 阶贝塞尔曲线路径,并获取曲线上的点。

function factorial(n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

function binomialcoefficient(n, i) {
    let res = factorial(n) / (factorial(i) * factorial(n - i));
    return math.floor(res);
}

function bernsteinpolynomial(n, i, t) {
    return binomialcoefficient(n, i) * math.pow(1 - t, n - i) * math.pow(t, i);
}

function getpointonbeziercurve(t, arr) {
    let x = 0;
    let y = 0;

    for (let i = 0; i < arr.length; i++) {
        let bernstein = bernsteinpolynomial(arr.length - 1, i, t);
        x += bernstein * arr[i].x;
        y += bernstein * arr[i].y;
    }

    return { x, y };
}

其中,getpointonbeziercurve 函数第一个参数 t 取值范围是 0到 1,该参数决定了曲线上的点的位置。第二个参数 arr 是控制点数组,该参数决定了贝塞尔曲线的阶数(即 n),例如:arr 传入的是 [p0, p1, p2, p3],那么对应的贝塞尔曲线的阶数 n就等于 3。

实现小球运动

接下来,我们需要实现小球沿着贝塞尔曲线运动,即不断更新小球的坐标位置,并调用 drawball 函数来绘制小球。

let t = 0;

const points = [
    { x: 100, y: 50 },
    { x: 200, y: 300 },
    { x: 700, y: -20 },
    { x: 500, y: 500 },
];

function animate() {
    ctx.clearrect(0, 0, canvas.width, canvas.height);

    const point = getpointonbeziercurve(t, points);
    drawball(point.x, point.y);

    t += 0.01;

    if (t > 1) {
        settimeout(() => {
            t = 0;
            requestanimationframe(animate);
        }, 1000);
    }
    else {
        requestanimationframe(animate);
    }
}

animate();

展示

完整代码

<!doctype html>
<html lang="zh-cn">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>canvas</title>
    <style>
        body {
            font-family: arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
        }

        canvas {
            border-radius: 15px;
            background-color: #ffffff;
        }
    </style>
</head>

<body>
    <canvas id="demo-canvas" width="800" height="600"></canvas>

    <script>
        const canvas = document.getelementbyid('demo-canvas');
        const ctx = canvas.getcontext('2d');

        const ball = {
            radius: 20,
            color: '#ff0000',
        };

        function drawball(x, y) {
            ctx.beginpath();
            ctx.arc(x, y, ball.radius, 0, math.pi * 2);
            ctx.fillstyle = ball.color;
            ctx.fill();
        }

        function factorial(n) {
            return n <= 1 ? 1 : n * factorial(n - 1);
        }

        function binomialcoefficient(n, i) {
            let res = factorial(n) / (factorial(i) * factorial(n - i));
            return math.floor(res);
        }

        function bernsteinpolynomial(n, i, t) {
            return binomialcoefficient(n, i) * math.pow(1 - t, n - i) * math.pow(t, i);
        }

        function getpointonbeziercurve(t, arr) {
            let x = 0;
            let y = 0;

            for (let i = 0; i < arr.length; i++) {
                let bernstein = bernsteinpolynomial(arr.length - 1, i, t);
                x += bernstein * arr[i].x;
                y += bernstein * arr[i].y;
            }

            return { x, y };
        }

        let t = 0;

        const points = [
            { x: 100, y: 50 },
            { x: 200, y: 300 },
            { x: 700, y: -20 },
            { x: 500, y: 500 },
        ];

        function animate() {
            ctx.clearrect(0, 0, canvas.width, canvas.height);

            const point = getpointonbeziercurve(t, points);
            drawball(point.x, point.y);

            t += 0.01;

            if (t > 1) {
                settimeout(() => {
                    t = 0;
                    requestanimationframe(animate);
                }, 1000);
            }
            else {
                requestanimationframe(animate);
            }
        }

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

</html>

扩展

在此基础上,我们可以添加更多的小球,让它们沿着随机化的贝塞尔曲线运动,从而形成更加复杂的动画效果。

<!doctype html>
<html lang="zh-cn">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>canvas</title>
    <style>
        body {
            font-family: arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
        }

        canvas {
            border-radius: 15px;
            background-color: #ffffff;
        }
    </style>
</head>

<body>
    <canvas id="canvas" width="800" height="600"></canvas>

    <script>
        const canvas = document.getelementbyid('canvas');
        const ctx = canvas.getcontext('2d');

        function getrandompoints() {
            const randomnumber = (min, max) => {
                const randombuffer = new uint32array(1);
                window.crypto.getrandomvalues(randombuffer);
                const number = randombuffer[0] / (0xffffffff + 1);
                return math.floor(number * (max - min) + min);
            }

            let points = [
                { x: parseint(canvas.width / 5), y: parseint(canvas.height / 2), },
                { x: parseint(canvas.width / 5 * 4), y: parseint(canvas.height / 2), },
            ];

            const count = randomnumber(2, 5);
            const minx = -100, maxx = 900, miny = -100, maxy = 700;

            for (let i = 0; i < count; i++) {
                points.splice(i + 1, 0, { x: randomnumber(minx, maxx), y: randomnumber(miny, maxy) });
            }

            return points;
        }

        function factorial(n) {
            return n <= 1 ? 1 : n * factorial(n - 1);
        }

        function binomialcoefficient(n, i) {
            let res = factorial(n) / (factorial(i) * factorial(n - i));
            return math.floor(res);
        }

        function bernsteinpolynomial(n, i, t) {
            return binomialcoefficient(n, i) * math.pow(1 - t, n - i) * math.pow(t, i);
        }

        function getpointonbeziercurve(t, arr) {
            let x = 0;
            let y = 0;

            for (let i = 0; i < arr.length; i++) {
                let bernstein = bernsteinpolynomial(arr.length - 1, i, t);
                x += bernstein * arr[i].x;
                y += bernstein * arr[i].y;
            }

            return { x, y };
        }

        const radius = 20;
        const colors = ['green', 'purple', 'orange'];

        let t = 0.0;
        let points = [getrandompoints(), getrandompoints(), getrandompoints()];

        function animate() {
            ctx.clearrect(0, 0, canvas.width, canvas.height);

            for (let i = 0; i < points.length; i++) {
                let pos = getpointonbeziercurve(t, points[i]);
                ctx.beginpath();
                ctx.arc(pos.x, pos.y, radius, 0, 2 * math.pi);
                ctx.fillstyle = colors[i];
                ctx.fill();
            }

            t += 0.01;

            if (t > 1) {
                settimeout(() => {
                    t = 0;
                    points = [getrandompoints(), getrandompoints(), getrandompoints()];
                    requestanimationframe(animate);
                }, 1000);
            }
            else {
                requestanimationframe(animate);
            }
        }

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

</html>

展示

以上就是使用javascript实现小球按照贝塞尔曲线运动的详细内容,更多关于javascript小球曲线运动的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com