实现一个简单的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
}

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

相关推荐
qq_411671986 分钟前
vue3 的模板引用ref和$parent
前端·javascript·vue.js
清幽竹客1 小时前
vue-37(模拟依赖项进行隔离测试)
前端·vue.js
vvilkim1 小时前
Nuxt.js 页面与布局系统深度解析:构建高效 Vue 应用的关键
前端·javascript·vue.js
滿1 小时前
Vue3 父子组件表单滚动到校验错误的位置实现方法
前端·javascript·vue.js
专注VB编程开发20年1 小时前
javascript的类,ES6模块写法在VSCODE中智能提示
开发语言·javascript·vscode
夏梦春蝉2 小时前
ES6从入门到精通:模块化
前端·ecmascript·es6
拓端研究室3 小时前
视频讲解:门槛效应模型Threshold Effect分析数字金融指数与消费结构数据
前端·算法
工一木子4 小时前
URL时间戳参数深度解析:缓存破坏与前端优化的前世今生
前端·缓存
半点寒12W6 小时前
微信小程序实现路由拦截的方法
前端
某公司摸鱼前端7 小时前
uniapp socket 封装 (可拿去直接用)
前端·javascript·websocket·uni-app