实现一个简单的Canvas动画

<canvas>是一个可以使用脚本 (通常为JavaScript) 来绘制图形的 HTML 元素。例如,它可以用于绘制图表、制作图片构图或者制作简单的动画。本文将实现一个经常在博客主页出现的背景动画,在此过程中巩固复习一下Canvas的相关知识

绘制静态图像

我们首先根据window的尺寸和devicePixelRatio确定画布尺寸

js 复制代码
const cvs = document.querySelector('canvas');
const ctx = cvs.getContext('2d');

function init() {
    cvs.width = window.innerWidth * devicePixelRatio;
    cvs.height = window.innerHeight * devicePixelRatio;
}

init();

因为我们最后的目的是要实现一个动画,我们会先编写一个通用的随机函数getRandom,借用这个随机函数编写一个绘制点的构造函数Point和一个绘制画的构造函数Graph

js 复制代码
// 生成随机数
function getRandom(min, max) {
    return Math.floor(Math.random() * (max + 1 - min) + min);
}

// 绘制点
class Point {
    constructor() {
        this.r = 6;
        this.x = getRandom(0, cvs.width - this.r / 2);
        this.y = getRandom(0, cvs.height - this.r / 2);
    }

    draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
        ctx.fillStyle = 'rgb(200, 200, 200)';
        ctx.fill();
    }
}

class Graph {
    constructor(pointNumber = 30, maxDis = 500) {
        this.points = new Array(pointNumber).fill(0).map(() => new Point());
        this.maxDis = maxDis;
    }

    draw() {
        for (let i = 0; i < this.points.length; i++) {
            const p1 = this.points[i];
            p1.draw();
            for (let j = i + 1; j < this.points.length; j++) {
                const p2 = this.points[j];
                const d = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
                if (d > this.maxDis) {
                    continue;
                }
                ctx.beginPath();
                ctx.moveTo(p1.x, p1.y);
                ctx.lineTo(p2.x, p2.y);
                ctx.closePath();
                ctx.strokeStyle = `rgba(200, 200, 200, ${0.8 - d / this.maxDis})`;
                ctx.stroke();
            }
        }
    }
}

以上我们完成了点线的绘制

绘制动态图像

动画实际上就是图像的不断刷新一点点的刷新,我们在不断的清空原来的图像,然后绘制的新的图像。我们首先在每次绘制图像的时候都使用requestAnimationFrame注册下一次的动画,这样实现了页面图像的不断刷新。然后我们需要确定的运动方向,由此设置X和Y两个方向的速度,根据初中物理知识,我们要想知道点在移动距离,必须还要有一个相对时间,最后的的移动距离的值是速度 * 时间

js 复制代码
class Point {
    constructor() {
        this.r = 6;
        this.x = getRandom(0, cvs.width - this.r / 2);
        this.y = getRandom(0, cvs.height - this.r / 2);
        this.xSpeed = getRandom(-50, 50);
        this.ySpeed = getRandom(-50, 50);
        this.lastDrawTime = null;
    }

    draw() {
        if(this.lastDrawTime){
            //根据运动时间,计算当前位置
            const now = Date.now()
            const t = (now - this.lastDrawTime) / 1000;
            let x = this.x + this.xSpeed * t
            let y = this.y + this.ySpeed * t
            this.x = x
            this.y = y
        }
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
        ctx.fillStyle = 'rgb(200, 200, 200)';
        ctx.fill();
        this.lastDrawTime = Date.now()
    }
}



class Graph {

    draw() {
        // 注册下一次画图
        requestAnimationFrame(() => {
             this.draw();
        });
        // 清空画布
        ctx.clearRect(0, 0, cvs.width, cvs.height);

优化

以上已经实现了基本的动画效果,但是有一个问题是点在运动时会越跑越远,超出我们的屏幕,下面我们要设置点的运动边界

js 复制代码
if(this.lastDrawTime){
  //根据运动时间,计算当前位置
  const now = Date.now()
  const t = (now - this.lastDrawTime) / 1000;
  let x = this.x + this.xSpeed * t
  let y = this.y + this.ySpeed * t
  if(x <= this.r || x>= cvs.width - this.r){
    this.xSpeed *= -1
   }
  if(y <= this.r || y>= cvs.height - this.r){
    this.ySpeed *= -1
  }
    this.x = x
    this.y = y
}

🔥🔥如果对您有一点帮助,给个👍鼓励一下吧!谢谢~🙏

相关推荐
界面开发小八哥几秒前
「Java EE开发指南」如何用MyEclipse构建一个Web项目?(一)
java·前端·ide·java-ee·myeclipse
谢道韫6668 分钟前
今日总结 2024-12-24
javascript·vue.js·elementui
一朵好运莲9 分钟前
React引入Echart水球图
开发语言·javascript·ecmascript
米奇妙妙wuu15 分钟前
react使用sse流实现chat大模型问答,补充css样式
前端·css·react.js
傻小胖20 分钟前
React 生命周期完整指南
前端·react.js
梦境之冢1 小时前
axios 常见的content-type、responseType有哪些?
前端·javascript·http
racerun1 小时前
vue VueResource & axios
前端·javascript·vue.js
J总裁的小芒果1 小时前
THREE.js 入门(六) 纹理、uv坐标
开发语言·javascript·uv
m0_548514771 小时前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
AndrewPerfect1 小时前
xss csrf怎么预防?
前端·xss·csrf