在vue3中使用canvas实现雨滴效果

在vue3中使用canvas实现雨滴效果

这是封装的一个组件DotAndRain(

<script setup>
import { ref, onMounted } from "vue";
import { onUnmounted } from "vue";let animationFrameId = null;const el = ref(null);
let canvas = null;
let ctx = null;
let dots = [];
let rains = [];onMounted(() => {canvas = el.value;canvas.width = 162;canvas.height = 146;ctx = canvas.getContext("2d");draw();animate();
});onUnmounted(() => {cancelAnimationFrame(animationFrameId);
});function draw() {const positions = [[[54, 16], 10],[[28, 80], 80],[[130, 114], 120]];for (const arr of positions) {const dot = new Dot(...arr[0]);dot.draw();dots.push(dot);const rain = new Rain(arr[1]);rain.draw();rains.push(rain);}
}function animate() {ctx.clearRect(0, 0, canvas.width, canvas.height);dots.forEach((dot) => {dot.move();});rains.forEach((rain) => {rain.move();});animationFrameId = requestAnimationFrame(animate);
}class Dot {radius = 3;speed = 0.08;range = 10;angle = Math.random() * Math.PI * 2;constructor(x, y) {this.x = x;this.y = y;this.originX = x;this.originY = y;}draw() {ctx.beginPath();ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);const line = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.radius);line.addColorStop(0, "#fff");line.addColorStop(1, "#62E9F9");ctx.fillStyle = line;// ctx.fillStyle = "#62E9F9";ctx.fill();ctx.closePath();}move() {// 计算下一个位置const nextX = this.x + Math.cos(this.angle) * this.speed;const nextY = this.y + Math.sin(this.angle) * this.speed;// 判断是否超出边界if (nextX > this.originX - this.range && nextX < this.originX + this.range && nextY > this.originY - this.range && nextY < this.originY + this.range) {this.x = nextX;this.y = nextY;} else {// 如果超出边界,则随机生成新的角度this.angle = Math.random() * Math.PI * 2;}this.draw();}
}class Rain {alpha = 0.8;width = 2;y = canvas.height;constructor(x) {this.x = x;this.init();}init() {this.alpha = 1;this.speed = Math.random() + 1;this.height = Math.random() * 40 + 30;this.y = canvas.height;}draw() {ctx.beginPath();ctx.lineWidth = 3; //宽度// ctx.globalAlpha = this.alpha; //设置透明度//创建横向渐变颜色,起点坐标至终点坐标const line = ctx.createLinearGradient(this.x, this.y, this.x + this.width, this.y + this.height);line.addColorStop(0, `rgba(62, 192, 255, ${this.alpha})`);line.addColorStop(0.6, `rgba(62, 192, 255, ${this.alpha / 2})`);line.addColorStop(1, "transparent");ctx.strokeStyle = line;ctx.moveTo(this.x, this.y);ctx.lineTo(this.x, this.y + this.height);ctx.closePath();ctx.stroke();}move() {this.alpha -= 0.01;this.y -= this.speed;if (this.y < 0) {this.init();}this.draw();}
}
</script><template><canvas ref="el" style="width: 162px; height: 146px"></canvas>
</template><style scoped lang="scss"></style>

上述代码实现了一个简单的雨滴效果,主要包括绘制雨滴和下落动画两个部分。下面我会详细解释代码中涉及到的关键部分:

1.初始化和绘制:

  • draw() 函数中,首先定义了三个雨滴和雨点的初始位置和大小,并通过循环创建了对应数量的 DotRain 对象,并调用它们的draw() 方法进行绘制。
  • Dot 类用于绘制雨滴的水滴效果,包括设置半径、速度、范围、角度等属性,并实现了 draw()move()
    方法来绘制和移动雨滴。
  • Rain 类用于绘制雨滴的下落效果,包括设置透明度、宽度、高度等属性,并实现了 init()draw()move()
    方法来初始化、绘制和控制雨滴的下落。

2.动画循环:

  • animate() 函数中,使用 requestAnimationFrame()
    创建了一个动画循环,不断清除画布内容并重新绘制雨滴和雨点,实现动态效果。
  • 在每一帧中,分别调用雨滴和雨点对象的 move() 方法,更新它们的位置和状态,并重新绘制在画布上。

3.雨滴效果绘制:

  • Dot 类通过绘制圆形并利用径向渐变填充,实现了水滴的效果,颜色由白色渐变为蓝色。
  • Rain 类通过绘制线条并利用线性渐变描边,实现了雨滴的下落效果,颜色从蓝色透明度逐渐减小到透明。

在App.vue文件中直接使用即可

<script setup>
import assets from '/src/assets/assets_item.png';
import DotAndRain from './components/DotAndRain.vue';
</script><template><div style="position: relative;width: 162px; height: 146px;"><div class="item-shadow"></div><div class="item-bg"></div><DotAndRain/></div>
</template><style scoped>
/* 电子围墙 */
.item-bg {background-image: url("/src/assets/assets_item.png");width: 162px;height: 146px;position: absolute;z-index: 4;
}.item-shadow::before {content: "";position: absolute;left: 0;bottom: 40px;width: 100%;height: 0;z-index: 2;background-image: linear-gradient(0deg, rgba(21, 54, 90, 1), transparent);background-repeat: repeat-y;background-size: 100% 100%;animation: wall 3s linear infinite;
}.item-shadow::after {content: "";position: absolute;left: 0;bottom: 40px;width: 100%;height: 0;z-index: 3;background-image: linear-gradient(0deg, rgba(21, 54, 90, 1), transparent);background-repeat: repeat-y;background-size: 100% 100%;animation: wall 3s linear infinite 1.5s;
}@keyframes wall {0% {height: 0;}20% {opacity: 1;}60% {height: calc(100% - 50px);}100% {opacity: 0;}
}
</style>

实现效果如下:

cavans实现雨滴

cavans快速入门

1.创建cavans

<script setup>
</script><template><div><canvas ref="canvas" height="600px" width="600px"></canvas></div>
</template><style scoped>
canvas {border: 1px solid #ccc;
}

在这里插入图片描述
2.获取CanvasRenderingContext2D对象进行绘制

  • 给canvas添加一个ref属性:
<canvas ref="canvas" height="300px" width="300px"></canvas>
  1. 获取canvas对象:
<script setup>
import { ref} from 'vue';const canvas = ref(null);
</script>
  • 渲染完成后获取CanvasRenderingContext2D对象:
<script setup>
import { ref, onMounted } from 'vue';const canvas = ref(null);
onMounted(() => {const ctx = canvas.value.getContext('2d');
});
</script>
  • 直线、圆圈、圆弧的绘制:
    具体请参考HTML Canvas参考手册
<script setup>
import { ref, onMounted } from 'vue';
const canvas = ref(null);onMounted(() => {const ctx = canvas.value.getContext('2d');//直线绘制// ctx.moveTo(100, 100);// ctx.lineTo(200, 200);// ctx.stroke();//圆圈绘制ctx.beginPath();ctx.arc(100, 75, 50, 0, 2 * Math.PI);ctx.stroke();//圆弧绘制// ctx.beginPath();// ctx.arc(100,75,50,90/180*Math.PI,2*Math.PI);// ctx.stroke();
});
</script>

完整模板如下:

<script setup>
import { ref, onMounted } from 'vue';
const canvas = ref(null);onMounted(() => {const ctx = canvas.value.getContext('2d');ctx.beginPath();ctx.arc(100, 75, 50, 0, 2 * Math.PI);ctx.stroke();
});
</script><template><div><canvas ref="canvas" height="300px" width="300px"></canvas></div>
</template><style scoped>
canvas {border: 1px solid #ccc;
}
</style>

效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/694799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5 原型模式 Prototype

1.模式定义: 指原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象 2.应用场景&#xff1a; 当代码不应该依赖于需要复制的对象的具体类时&#xff0c;请使用Prototype模式。 Spring源码中的应用 org.springframework.beans.factory.support.AbstractB…

蓝桥杯嵌入式第12届真题(完成) STM32G431

蓝桥杯嵌入式第12届真题(完成) STM32G431 题目 程序 main.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body**************************…

Linux常见的指令

目录 01. ls 指令02. pwd命令03. cd 指令04. touch指令05.mkdir指令&#xff08;重要&#xff09;&#xff1a;06.rmdir指令 && rm 指令&#xff08;重要&#xff09;&#xff1a;07.man指令&#xff08;重要&#xff09;&#xff1a;08.cp指令&#xff08;重要&#x…

浅谈maven的生命周期

正文: 在Maven中,生命周期定义了项目构建过程的不同阶段以及在每个阶段中执行的插件目标。Maven的生命周期是由一系列阶段组成的,每个阶段都有一个唯一的标识符。 Clean生命周期:用于清理项目的构建目录。它包含以下阶段: pre-clean:执行在清理操作之前的任何操作。clea…

【Vuforia+Unity】AR05-实物3D模型识别功能实现

对于3D物体的识别&#xff0c;可以是虚拟的也可以是实物的&#xff0c;但是对于虚拟的三维模型意义不大&#xff0c;我们完全可以把三维模型放在屏幕上截一张图&#xff0c;以图片识别的方式召唤数字内容&#xff0c;不过在虚拟现实中或许有用。 因此本文探讨的技术路线主要是…

【云原生】Docker consul的容器服务更新与发现

目录 什么是服务注册与发现 什么是consul consul提供的一些关键特性&#xff1a; consul 部署 consul服务器 1. 建立 Consul 服务 设置代理&#xff0c;在后台启动 consul 服务端 2. 查看集群信息 查看members状态 查看集群状态 3. 通过 http api 获取集群信息 regi…

vue-router 三级路由,路由跳转页面异常白屏或404,或刷新三级路由页面后一级和二级路由菜单丢失

问题描述 情况1. vue-router 定义三级路由&#xff0c;路由跳转了&#xff0c;页面404或者白屏情况2. 点击菜单三级路由后&#xff0c;刷新页面后一级和二级路由菜单丢失 解决方案&#xff1a; 某些时候是因为二级和三级的路由共用router-view&#xff0c;可以使用router-vi…

搭建SQL 注入平台

sqli-labs是一款学习SQL 注入的开源平台&#xff0c;共有75种不同类型的注入&#xff0c;在本书 的同步网站下载完压缩包后并解压&#xff0c;复制源码然后将其粘贴到网站的目录中&#xff0c;进入 MySQL 管理中的phpMyAdmin, 打开http://127.0.0.1/phpMyAdmin/, 在数据库…

day08-实战-今日指数

今日指数-day08 1. 个股最新分时行情数据 1.1 个股最新分时行情功能说明 1&#xff09;个股最新分时行情功能原型 2&#xff09;个股最新分时行情数据接口分析 功能描述&#xff1a;获取个股最新分时行情数据&#xff0c;主要包含&#xff1a;开盘价、前收盘价、最新价、最…

量子加密机的工作原理是什么

量子加密机&#xff0c;作为现代加密技术的一大飞跃&#xff0c;正逐渐成为信息安全领域的研究热点。与传统的加密方法相比&#xff0c;量子加密技术以其独特的优势&#xff0c;为信息安全提供了更为坚实的保障。 量子加密的核心在于利用量子力学的特性&#xff0c;尤其是量子纠…

MySQL 多表操作

一.多表关系 1.一对一关系 一个学生只有一张身份证&#xff1b;一张身份证只能对应一个学生。 在任一表中添加外键&#xff0c;指向另一方主键&#xff0c;确保一对一关系。 一般一对一关系很少见&#xff0c;遇到一对一关系的表最好合并。 2.一对多/多对一关系 一个部门…

国产chat gpt推荐

下述网站响应非常快 会持续更新的! 付费&#xff1a; 小名言 免费&#xff1a; AIchatOS 百度的文心一言

【虚拟仿真】Unity3D中实现3DUI,并且实现Button、InputField、Toggle等事件绑定

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 最近在项目中需要用到3DUI的展示,之前一般会用TextMeshPro进行展示: 但是,后面又需要添加按钮、Toggle等…

船运物流管理系统|基于springboot船运物流管理系统设计与实现(源码+数据库+文档)

船运物流管理系统目录 目录 基于springboot船运物流管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员登录 2、货运单管理 3、公告管理 4、公告类型管理 5、新闻管理 6、新闻类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 …

【线性代数基础】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述概要知识图谱 简述概要 关于线性代数的基础知识。 知识图谱 1.基本概念&#xff1a; 向量&#xff1a;向量是一个有方向的量&#xff0c;可以用一组数&#xff08;称为坐标&#xff09;来表示。在二维空间中&#x…

4、电源管理入门之子系统reset

目录 1. 简介 2. consumer-驱动软件 3. provider-reset驱动 3.1 整体介绍 3.2 reset复位API说明 之前的文章电源管理入门-1关机重启详解介绍了整机SoC的重启也可以说是reset,那么子系统的reset,例如某个驱动(网卡、USB等)或者某个子系统(NPU、ISP等运行在独立的M核或…

Windows安装PHP及在VScode中配置插件,使用PHP输出HelloWorld

安装PHP PHP官网下载地址(8.3版本)&#xff1a;PHP For Windows&#xff1a;二进制文件和源代码发布 点击下载.zip格式压缩包&#xff1a; 历史版本在Old archives中下载。推荐在Documentation download中下载官方文档&#xff0c;方便学习。 下载完成后在一个顺眼的地方解压压…

MySQL学习笔记3: MySQL数据库基础

目录 前言目标数据库操作&#xff08;针对database 的操作&#xff09;1. 创建数据库 create database 数据库名;2. 查看数据库 show databases;3. 选中数据库 use 数据库名;4. 删除数据库 drop database 数据库名; mysql中支持的数据类型1. 数值类型: NUMERIC(M,D)2. 字符串类…

实现Slider 滑块组件标记动态变化

实现以上效果&#xff0c;下拉框、slider滑块、按钮都在同一行&#xff0c;设置flex布局后&#xff0c;发现silider滑块最右边的标记数字一直都如下竖着显示&#xff0c;后来通过给源组件的标记区.el-slider__marks-text增加一个宽度后解决该问题。 <template><div>…

Linux实验记录:使用LNMP架构部署动态网站环境

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 备注&#xff1a; LNMP动态网站部署架构是一套由&…