当前位置: 首页 > news >正文

【canvas】动画

文章目录

    • 动画基本步骤
    • 动画示例
      • 1. 时钟
      • 2. 循环全景照片
      • 3. 小球边界碰撞检测

动画基本步骤

  1. 清空 canvas :使用 clearRect
  2. 绘制动画图形: 这一步才是重绘动画帧
  3. 操控动画:定时执行重绘的方法,可以用 setInterval()setTimeout() requestAnimationFrame()

示例:

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  // 绘制动画内容
  
  requestAnimationFrame(draw);
}
draw();

动画示例

1. 时钟

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Canvas Animation</title>
        <style>
            canvas {
                border: 1px solid black;
            }
        </style>
    </head>
    <body>
        <canvas id="canvas" width="300" height="300">1</canvas>

        <script>
            const canvas = document.getElementById("canvas");
            const ctx = canvas.getContext("2d");

            function draw() {
                ctx.save();

                ctx.clearRect(0, 0, 300, 300);
                ctx.translate(150, 150);
                ctx.rotate(-Math.PI / 2);

                ctx.strokeStyle = "blue";
                ctx.lineWidth = 8;
                ctx.beginPath();
                ctx.arc(0, 0, 100, 0, 2 * Math.PI);
                ctx.stroke();

                ctx.strokeStyle = "black";
                ctx.lineCap = "round";
                ctx.textAlign = "center";
                ctx.textBaseline = "middle";
                for (let i = 0; i < 60; i++) {
                    ctx.beginPath();

                    if (i % 5 === 0) {
                        // 小时刻度
                        ctx.lineWidth = 4;
                        ctx.moveTo(90, 0);
                        ctx.lineTo(75, 0);

                        ctx.fillText(i / 5, 65, 0);
                    } else {
                        // 分钟刻度
                        ctx.lineWidth = 2;
                        ctx.moveTo(90, 0);
                        ctx.lineTo(85, 0);
                    }
                    ctx.stroke();

                    ctx.rotate(Math.PI / 30);
                }

                const time = new Date();
                const seconds = time.getSeconds();
                const minutes = time.getMinutes();
                const hours = time.getHours();

                // 时针
                ctx.save();
                ctx.rotate((Math.PI / 6) * hours + (Math.PI / 360) * minutes + (Math.PI / 21600) * seconds);
                ctx.beginPath();
                ctx.lineWidth = 8;
                ctx.moveTo(-10, 0);
                ctx.lineTo(60, 0);
                ctx.stroke();
                ctx.restore();

                // 分针
                ctx.save();
                ctx.rotate((Math.PI / 30) * minutes + (Math.PI / 1800) * seconds);
                ctx.beginPath();
                ctx.lineWidth = 4;
                ctx.moveTo(-15, 0);
                ctx.lineTo(80, 0);
                ctx.stroke();
                ctx.restore();

                // 秒针
                ctx.save();
                ctx.strokeStyle = "red";
                ctx.rotate((Math.PI / 30) * seconds);
                ctx.beginPath();
                ctx.moveTo(0, 0);
                ctx.lineTo(80, 0);
                ctx.stroke();
                ctx.restore();

                ctx.restore();

                requestAnimationFrame(draw);
            }
            draw();

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

2. 循环全景照片

图片地址:测试图片

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Canvas Animation</title>
        <style>
            canvas {
                border: 1px solid black;
            }
        </style>
    </head>
    <body>
        <canvas id="canvas" width="800" height="200">1</canvas>

        <script>
            const canvas = document.getElementById("canvas");
            const ctx = canvas.getContext("2d");

            const image = new Image();
            image.src = "./assets/park.jpg";

            var CanvasXSize = 800;
            var CanvasYSize = 200;
            var speed = 30;
            var dx = 0.75;
            var x = 0;
            var imgW;
            var imgH;
            var clearX;
            var clearY;

            image.onload = () => {
                imgW = image.width;
                imgH = image.height;

                if (imgW > CanvasXSize) {
                    clearX = imgW;
                } else {
                    clearX = CanvasXSize;
                }
                if (imgH > CanvasYSize) {
                    clearY = imgH;
                } else {
                    clearY = CanvasYSize;
                }

                setInterval(draw, speed);
            };

            function draw() {
                ctx.clearRect(0, 0, clearX, clearY);

                if (x > CanvasXSize) {
                    x = CanvasXSize - imgW;
                }

                // draw aditional image
                if (x > CanvasXSize - imgW) {
                    ctx.drawImage(image, x - imgW + 1, 0, imgW, imgH);
                }

                ctx.drawImage(image, x, 0, imgW, imgH);

                x += dx;
            }
        </script>
    </body>
</html>

3. 小球边界碰撞检测

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>鼠标追踪动画</title>
        <style>
            canvas {
                border: 1px solid black;
            }
        </style>
    </head>
    <body>
        <canvas id="canvas" width="600" height="400">1</canvas>

        <script>
            const canvas = document.getElementById("canvas");
            const ctx = canvas.getContext("2d");

            var ball = {
                x: 100,
                y: 100,
                radius: 25,
                vx: 5,
                vy: 2,
                color: "blue",
                draw: function () {
                    ctx.clearRect(0, 0, canvas.width, canvas.height);

                    // 长尾效果效果(注释上面clearRect)
                    // ctx.fillStyle = "rgba(255, 255, 255, 0.4)";
                    // ctx.fillRect(0, 0, canvas.width, canvas.height);

                    ctx.beginPath();
                    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
                    ctx.fillStyle = this.color;
                    ctx.fill();
                },
            };

            function anim() {
                requestAnimationFrame(anim);
                ball.draw();
                ball.x += ball.vx;
                ball.y += ball.vy;
                ball.vy *= 0.99;
                ball.vy += 0.25;

                if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
                    ball.vx = -ball.vx;
                }

                if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
                    ball.vy = -ball.vy;
                }
            }

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

相关文章:

  • 【原创】Open WebUI 本地部署
  • gtest 和 gmock讲解
  • 物理内存组织与分配的核心概念
  • Spring Boot 流式响应豆包大模型对话能力
  • 在ubuntu 24.04.2 通过 Kubeadm 安装 Kubernetes v1.31.6
  • 简洁的个人地址发布页HTML源码
  • conda环境管理 kernel注册到jupyter notebook
  • nginx+keepalived负载均衡及高可用
  • 算法之领域算法
  • Web-to-Web和Server-to-Serve归因方法
  • 一文弄懂TCP断开连接时候的四次挥手
  • iOS接入Flutter项目
  • HTTP~文件 MIME 类型
  • 【量化科普】Drawdown,回撤
  • 基于log4j的自定义traceid实现
  • Spring AOP(教科书式的教程)
  • FASIONAD:自适应反馈的类人自动驾驶中快速和慢速思维融合系统
  • 使用AoT让.NetFramework4.7.2程序调用.Net8编写的库
  • QT异步编程之线程池QThreadPool
  • Chromium项目相关
  • 做网站域名转出挂靠服务器/网站排名优化课程
  • wordpress 资源站点/厦门seo屈兴东
  • 免费做淘宝店铺招牌的网站/今日的头条新闻
  • 网站建设协议书/郑州seo优化大师
  • 电商网站开发教程/热门推广平台
  • 中材建设有限公司招标网站/求职seo推荐