《经典复现----学思路而不只学代码》雪花飘落代码实现,类方法实现,掌握方法,做自己的哈姆雷特哦~

大概就是觉得网上这类的文章很多,而且有点乱,就总结了一波
结果图如下(用QQ录制然后ps转gif就成这样了):
在这里插入图片描述


读前须知

  • 在观看文章之前大家最好有一些canvas的知识,不过没有也没有关系,这里用到的知识点并不多,看到不懂的再去查一下好了,在这里的代码还是很容易理解的
  • 文章会涉及到部分es6相关内容,但是不影响阅读,文章后面会给出类写法的代码,也算是总结一波思路,希望大家在我的文章里学到的是思路,而不是代码
  • 希望大家学习文章的过程中代码更多的是自己动手敲,而不是一味的复制
  • 另外,在学习过程中重点在于展示思路,所以效果可能与文章图片不同,但文章最后给出的类形式的代码则是和真正效果一样的(除了一点点因为ps转换所导致的效果)

一、实现思路

要实现雪花飘落效果,实际上关键之处只需要小小的两步,其一就是需要将雪花随机遍布屏幕的位置,其二就是要更新雪花的位置。

二、实现步骤

1.基本设置

这里是基本的代码格式,这里直接copy就可以了:
index.html文件中:

<!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>Make it Snow</title>
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <div class="container">
        <canvas id="canvas"></canvas>
        <section class="section">
            <div class="text">
                <p>Make it Snow.</p>
            </div>
        </section>
    </div>
</body>
<script type="text/javascript" src="./index.js"></script>
</html>

index.css文件中:(图片自己找一个,合适的背景就可)

html {
    /* background-image: url('');这里加背景图片 */
    background-size: cover;
}
html {
    background-color: #000;
}

canvas {
    z-index: 2;
}

.text {
    text-align: center;
    color: #ffffff6b;
    font-size: 28px;
    width: 100%;
    top: 130px;
    position: absolute;
    margin: 0 auto;
    display: block;
}

index.js文件:

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let w, h;//canvas的长宽
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
//返回min和max中的随机数
function random(min, max) {
    return min + Math.random() * (max - min + 1);
};

function clientResize() {
    w = canvas.width = window.innerWidth;
    h = canvas.height = window.innerHeight;
};
window.addEventListener("resize", clientResize);

3.雪花生成

首先,我们需要定义变量particlesOnScreen,是要显示在屏幕上的雪花的数量,然后定义一个数组particlesArray用来设定这些雪花的参数,在这里,我们需要设置雪花的坐标,以及对应的圆的半径,以及雪花下落和左右移动的速度

let particlesOnScreen = 245;//设置雪花的数量
let particlesArray = [];//雪花参数数组
// 设置每个雪花的参数
function createSnowFlakes() {
    for (let i = 0; i < particlesOnScreen; i++) {
        particlesArray.push({
            x: Math.random() * w,
            y: Math.random() * h,
            speedX: random(-11, 11),
            speedY: random(7, 15),
            radius: random(0.5, 4.2),
        })
    }
};
createSnowFlakes();

4.雪花呈现在画布上

这里就是调用canvas相关的方法根据参数画出圆:

// 画出雪花的位置
function drawSnowFlakes() {
    for (let i = 0; i < particlesArray.length; i++) {
        ctx.beginPath();
        //画圆弧
        ctx.arc(particlesArray[i].x, particlesArray[i].y, particlesArray[i].radius, 0,Math.PI * 2,false);
        //使用白色填充
        ctx.fillStyle = "#fff";
        ctx.fill();
    }
};

5.雪花位置更新

根据横纵方向速度移动雪花位置,如果已经超过了画布范围,就回到最上面:

// 移动雪花的位置
function moveSnowFlakes() {
    for (let i = 0; i < particlesArray.length; i++) {
        particlesArray[i].x += particlesArray[i].speedX;
        particlesArray[i].y += particlesArray[i].speedY;
		//如果超过画布大小
        if (particlesArray[i].y > h) {
            particlesArray[i].x = Math.random() * w * 1.5;
            particlesArray[i].y = -50;
        }
    }
};

6.刷新画布

不断重绘画布实现效果:

// 更新画布
function updateSnowFall() {
	//清空画布
    ctx.clearRect(0, 0, w, h);
    drawSnowFlakes();
    moveSnowFlakes();
};
setInterval(updateSnowFall, 50);

至此我们就可以得到(不加背景图):
在这里插入图片描述


7.放一下完整代码

index.js文件

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");


let w, h;//canvas的长宽
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;

function random(min, max) {
    return min + Math.random() * (max - min + 1);
};

function clientResize(ev) {
    w = canvas.width = window.innerWidth;
    h = canvas.height = window.innerHeight;
};
window.addEventListener("resize", clientResize);

let particlesOnScreen = 245;//设置雪花的数量
let particlesArray = [];//雪花参数数组
// 设置每个雪花的参数
function createSnowFlakes() {
    for (let i = 0; i < particlesOnScreen; i++) {
        particlesArray.push({
            x: Math.random() * w,
            y: Math.random() * h,
            opacity: Math.random(),
            speedX: random(-11, 11),
            speedY: random(7, 15),
            radius: random(0.5, 4.2),
        })
    }
};
createSnowFlakes();

// 画出雪花的位置
function drawSnowFlakes() {
    for (let i = 0; i < particlesArray.length; i++) {
        ctx.beginPath();
        //画圆弧
        ctx.arc(particlesArray[i].x, particlesArray[i].y, particlesArray[i].radius, 0,Math.PI * 2,false);
        //使用白色填充
        ctx.fillStyle = "#fff";
        ctx.fill();
    }
};

// 移动雪花的位置
function moveSnowFlakes() {
    for (var i = 0; i < particlesArray.length; i++) {
        particlesArray[i].x += particlesArray[i].speedX;
        particlesArray[i].y += particlesArray[i].speedY;

        if (particlesArray[i].y > h) {
            particlesArray[i].x = Math.random() * w * 1.5;
            particlesArray[i].y = -50;
        }
    }
};

// 更新画布
function updateSnowFall() {
    ctx.clearRect(0, 0, w, h);
    drawSnowFlakes();
    moveSnowFlakes();
};


setInterval(updateSnowFall, 50);


三、类方法实现

这里再用类方法实现一下以上效果,其中为了达到更好的效果,会有一些代码改动,有问题请到评论区或私信。
类方法的实现:

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let w, h;//canvas的长宽
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;

function random(min, max) {
    return min + Math.random() * (max - min + 1);
};

function clientResize() {
    w = canvas.width = window.innerWidth;
    h = canvas.height = window.innerHeight;
};
window.addEventListener("resize", clientResize);

class RainFall {
    constructor(particlesOnScreen) {
        this.particlesOnScreen = particlesOnScreen;
        this.particlesArray = [];
        this.#createSnowFlakes();
    }
    update() {
        this.particlesArray.forEach(e => {
            e.x += e.speedX;
            e.y += e.speedY;
            if (e.y > h) {
                e.x = Math.random() * w * 1.5;
                e.y = -50;
            }
        })
    }
    draw() {
        this.particlesArray.forEach(item => {
            let gradient = ctx.createRadialGradient(item.x, item.y, 0, item.x, item.y, item.radius);

            gradient.addColorStop(0, "rgba(255, 255, 255," + item.opacity + ")");  // 白色
            gradient.addColorStop(.8, "rgba(210, 236, 242," + item.opacity + ")");  // 带蓝
            gradient.addColorStop(1, "rgba(237, 247, 249," + item.opacity + ")");   // 浅蓝

            ctx.beginPath();

            ctx.arc(item.x,item.y,item.radius, 0,Math.PI * 2, false);

            ctx.fillStyle = gradient;
            ctx.fill();
        })
    }
    // 设置每个雪花的参数
    //每个雪花包括雪花的坐标,雪花的透明度,雪花的左右,下落速度,半径
    #createSnowFlakes() {
        for (let i = 0; i < this.particlesOnScreen; i++) {
            this.particlesArray.push({
                x: Math.random() * w,
                y: Math.random() * h,
                opacity: Math.random(),
                speedX: random(-11, 11),
                speedY: random(7, 15),
                radius: random(0.5, 4.2),
            })
        }
    };
}

let rainFall = new RainFall(100);

// 更新画布
function drawCanvas() {
    ctx.clearRect(0, 0, w, h);
    rainFall.update();
    rainFall.draw();
    requestAnimationFrame(drawCanvas);
};
drawCanvas();

总结

所谓总结,当然最好能够起到举一反三的作用了
那么,当我们再实现类似的效果时,我们的重心便是物体的绘制、以及形状的运动,实现了这些,其他的基本上就是copy了。
如果文章对你有帮助的话,请留下你的赞哦,这对我非常重要,谢谢!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值