- <template>
- <!-- 降雨效果canvas -->
- <div class="canvasRainPage">
- <!-- 降雨 -->
- <canvas id="canvasRain"></canvas>
-
- <!-- 降雪 -->
- <canvas id="canvasSnow"></canvas>
- </div>
- </template>
-
- <script setup>
- const { proxy } = getCurrentInstance();
- const timer = ref(null);
- const timerAll = ref(null);
-
- // 画笔
- const ctx = ref(null);
- const ctxSnow = ref(null);
- // 画布的宽高
- let w = window.innerWidth;
- let h = window.innerHeight;
- // 存放雨滴的数组
- let arr = [];
- // 雨滴的数量
- const size = ref(300);
- // 雨滴的构造函数
- class Rain {
- x = random(w);
- y = random(h);
- ySpeed = random(2) + 8;
- show() {
- drawLine(this.x, this.y);
- }
- run() {
- if (this.y > h) {
- this.y = 0;
- this.x = random(w);
- }
- this.y = this.y + this.ySpeed;
- }
- }
- // 画线(雨滴)
- function drawLine(x1, y1) {
- ctx.value.beginPath();
- ctx.value.strokeStyle = "rgba(35, 195, 255, 1)";
- ctx.value.moveTo(x1, y1);
- // 雨长度
- ctx.value.lineTo(x1, y1 + 20);
- ctx.value.stroke();
- }
- // 生成随机数
- function random(num) {
- return Math.random() * num;
- }
- // 开始
- function start() {
- for (let i = 0; i < size.value; i++) {
- let rain = new Rain();
- arr.push(rain);
- rain.show();
- }
- timer.value = setInterval(() => {
- ctx.value.clearRect(0, 0, w, h);
- for (let i = 0; i < size.value; i++) {
- arr[i].show();
- arr[i].run();
- }
- }, 30);
- }
- // 初始化
- function init(ctx1) {
- ctx.value = ctx1;
- start();
- }
-
- // 清除画布
- function clearDraw() {
- ctx.value.clearRect(0, 0, w, h);
- }
-
- // 初始化
- function initCanvas() {
- const canvas = document.querySelector("#canvasRain");
- ctx.value = canvas.getContext("2d");
- canvas.width = w;
- canvas.height = h;
- init(ctx.value);
- // 1-12个月的不同降雨量变化
- let rainArr = [
- { month: "1", rain: 300 },
- { month: "2", rain: 350 },
- { month: "3", rain: 400 },
- { month: "4", rain: 450 },
- { month: "5", rain: 550 },
- { month: "6", rain: 600 },
- { month: "7", rain: 1200 },
- { month: "8", rain: 700 },
- { month: "9", rain: 600 },
- { month: "10", rain: 460 },
- { month: "11", rain: 400 },
- { month: "12", rain: 300 },
- ];
- let i = 0;
- timerAll.value = setInterval(() => {
- size.value = rainArr[i].rain;
- i++;
- if (i == 12) i = 0;
- init(ctx.value); //降雨效果
- // 下雪效果
- if (i >= 2 && i <= 10) {
- ctxSnow.value && ctxSnow.value.clearRect(0, 0, w, h); // 清除画布重新渲染
- ctxSnow.value = null;
- } else {
- initSnow();
- }
- }, 2083);
- }
-
- // 降雪效果
- function initSnow() {
- const canvas2 = document.querySelector("#canvasSnow");
- ctxSnow.value = canvas2.getContext("2d");
- // 设置canvas画布大小
- canvas2.width = w;
- canvas2.height = h;
-
- const config = {
- number: 300, // 生成的雪花数量
- snowArr: [],
- pic: "https://www.deanhan.cn/wp-content/uploads/2017/12/snow.png", // 雪花图片
- };
- let snowImg = new Image();
- snowImg.src = config.pic;
-
- for (let i = 0; i < config.number; i++) {
- config.snowArr.push({
- x: Math.random() * w, // 定义每片雪花的X轴
- y: Math.random() * h, // Y轴
- toX: Math.random(), // 雪花每一次渲染的X距离
- toY: Math.random() * 1 + 5, //速度
- size: Math.random() * 20 + 5, // 雪花的大小
- });
- }
-
- const dropAnimation = () => {
- if (!!!ctxSnow.value) return;
- ctxSnow.value.clearRect(0, 0, w, h); // 清除画布重新渲染
- for (let i = 0; i < config.snowArr.length; i++) {
- let snow = config.snowArr[i];
- // ctx.beginPath(); //绘制圆形雪花 后面直接图片代替
- // ctx.arc(snow.x, snow.y, snow.size, 0, Math.PI * 2, true);
- // ctx.fillStyle = '#666';
- // ctx.fill();
- ctxSnow.value.drawImage(snowImg, snow.x, snow.y, snow.size, snow.size);
-
- snow.x = snow.x > w ? 0 : snow.x + snow.toX; // 每调一次函数向右移动一点
- snow.y = snow.y > h ? 0 : snow.y + snow.toY; // 向下移动
- }
- requestAnimationFrame(dropAnimation);
- };
- requestAnimationFrame(dropAnimation);
- }
-
- onMounted(() => {
- initCanvas();
- initSnow();
- });
- onBeforeUnmount(() => {
- if (timer.value) clearInterval(timer.value);
- if (timerAll.value) clearInterval(timerAll.value);
- clearDraw();
- ctxSnow.value && ctxSnow.value.clearRect(0, 0, w, h);
- });
- </script>
-
- <style lang="scss" scoped>
- .canvasRainPage {
- width: 100%;
- height: 100%;
- background: rgba(0, 59, 109, 0.2);
- position: absolute;
- left: 0px;
- top: 0px;
- z-index: 100;
- pointer-events: none;
- #canvasRain {
- position: absolute;
- left: 0px;
- top: 0px;
- z-index: 102;
- }
- #canvasSnow {
- position: absolute;
- left: 0px;
- top: 0px;
- z-index: 101;
- }
- }
- </style>