likes
comments
collection
share

自己实现一个樱花🌸落下的动态-学校的樱花开了,让我们一起去看看吧

作者站长头像
站长
· 阅读数 14

樱花🌸落下的动态

最近看到了一个樱花满地飞的视频,于是看到有大佬想着自己用html实现这样一个页面,然后我也去学习学习!其实,主要实现的原理,就是通过canvas画图,将很多樱花随机的生成在不同位置,然后每一帧的时候位置慢慢发生改变!

先看效果 其中里面掉落的樱花就是我们自己通过canvas做出来的。 自己实现一个樱花🌸落下的动态-学校的樱花开了,让我们一起去看看吧

先看整体布局

可以看到我们只是单纯的设置了一个canvas对象,然后设置了一下背景图片充当背景。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>樱花背景</title>
  <style>
    body{
        background-image: url(https://gitee.com/unfortunately-there-is-no-if/img/raw/master/Image/bg.webp);
        background-repeat: no-repeat;
        background-size:cover;
    }
  </style>
</head>
<body>
    <canvas></canvas>
</body>
<script src="./script.js"></script>
</html>

js代码

这段代码实现了一个美丽的樱花飘落的效果。它会在页面中生成一个 canvas 元素,然后使用 Canvas API 来绘制樱花(花瓣),并在绘制过程中实现花瓣的飘落效果。除此之外,它还根据鼠标位置来调整花瓣的飘落速度和位置,使整个效果更加动态。

这段代码主要分为三个部分。第一部分是创建了一个 canvas 元素,设置了它的宽高,同时获取了 2D 绘图环境。第二部分是创建了一个樱花类(Sakura),并通过构造函数来初始化每个樱花的位置、速度、透明度等属性。这些属性可以随机生成,使得每个花瓣都有一些差异,增加了整个效果的美感。第三部分是渲染函数(render),它会在每一帧调用樱花类的 animate 方法来更新樱花的位置和状态,并在更新后再次调用 draw 方法来绘制相应的花瓣。

// 获取canvas元素
const canvas = document.querySelector('canvas');

// 设置canvas画布的宽高为浏览器视口宽高
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// 使用2d的绘图方式
const ctx = canvas.getContext('2d');

// 定义花瓣的数量
const SAKURA_SUM = 220;
// 花瓣数组
const sakuraArray = [];

/**
 * 定义花瓣类
 */
class Sakura {
    // 构造方法
    constructor() {
        // 随机生成花瓣的x, y坐标
        this.x = Math.random() * canvas.width;
        this.y = (Math.random() * canvas.height * 2) - canvas.height;
        // 随机生成花瓣的宽高
        this.width = Math.random() * 15 + 30;
        this.height = Math.random() * 12 + 25;
        // 随机透明度
        this.opacity = this.width / 50;
        // 设置一个随机数,后面实现旋转角度效果时会用到
        this.rotate = Math.random();
        // 速度初始化
        this.xSpeed = Math.random() * 2 + 1;
        this.ySpeed = Math.random() + 1.5;
        this.rotateSpeed = Math.random() * 0.02;
    }

    // 绘制
    draw() {
        // 当花瓣超过canvas画布边界后,重新设置花瓣的坐标、速度、和转速
        // 实现花瓣连续飘落的效果
        if (this.x > canvas.width || this.y > canvas.height) {
            this.x = -sakuraImg.width; // 刚好藏住
            this.y = (Math.random() * canvas.height * 2) - canvas.height;
            this.rotate = Math.random();
            this.rotateSpeed = Math.random() * 0.02;
            this.xSpeed = Math.random() * 2 + 0.5;
            this.ySpeed = Math.random() + 1;
        }

        // ctx.globalAlpha 为 canvas 全局透明度设置基准值,实现绘制出来的花瓣具有透明度效果
        ctx.globalAlpha = this.opacity;

        // 随机旋转花瓣旋转角度,cos和sin的范围均为[-1, 1],加入调整系数,保证花瓣变形可控
        const cos = Math.cos(this.rotate) * [0.2, 0.6][Math.floor(Math.random() * 2)];
        const sin = Math.sin(this.rotate) * [0.2, 0.6][Math.floor(Math.random() * 2)];

        // 绘制花瓣,将canvas坐标系的原点设置在花瓣的左上角
        ctx.setTransform(cos, sin, -sin, cos, this.x, this.y);
        ctx.drawImage(
            sakuraImg,
            0,
            0,
            this.width * [0.6, 0.8][Math.floor(Math.random() * 2)],
            this.height * [0.6,0.8][Math.floor(Math.random() * 2)]
        );
        ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置canvas坐标系为初始状态
    }

    // 花瓣动画
    animate() {
        // 修改花瓣的属性,使花瓣位置发生变化
        this.x += this.xSpeed + mouseX * 5;
        this.y += this.ySpeed + mouseX * 2;
        this.rotate += this.rotateSpeed;
        // 绘制花瓣
        this.draw();
    }
}

/**
 * 定义渲染方法
 */
function render() {
    // 使用clearRect方法清除画布内的内容,以便下一次绘制新的内容
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 遍历花瓣数组,进行花瓣动画绘制
    sakuraArray.forEach(sakura => sakura.animate());
    // 使用requestAnimationFrame方法进行高效的动画渲染,保证在浏览器的刷新频率下去更新动画
    window.requestAnimationFrame(render);
}

// 加载花瓣图片
const sakuraImg = new Image();
sakuraImg.src = 'https://gitee.com/unfortunately-there-is-no-if/img/raw/master/Image/sakura.png';
// 等花瓣图片加载完毕,将数目为SAKURA_SUM的花瓣实例保存到数组中
sakuraImg.addEventListener('load', () => {
    for (let i = 0; i < SAKURA_SUM; i++) {
        sakuraArray.push(new Sakura())
    }
    // 开始渲染花瓣动画
    render();

    // 监听浏览器窗口大小变化,重新设置canvas的宽高
    window.addEventListener('resize', () => {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    });
});
  // 定义鼠标、触屏事件监听回调函数
  let mouseX = 0;
  function touchHandler(e) {
      // clinetX: 客户端区域的水平坐标 (与页面坐标不同)
      // 修改鼠标在窗口中的位置,使花瓣在飘动时受到鼠标位置的影响
      mouseX = (e.clientX || e.touches[0].clientX) / window.innerWidth;
  }
  // 监听鼠标移动事件和触屏移动事件
  window.addEventListener('mousemove', touchHandler);
  window.addEventListener('touchmove', touchHandler);

源码

掘金/樱花背景 · Mr-W-Y-P/Html-css-js-demo - 码云 - 开源中国 (gitee.com)