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

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

相关推荐
Myli_ing16 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风18 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
PandaCave25 分钟前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
软件小伟27 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7011 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue