js实现红包雨功能(canvas,react,ts),包括图片不规则旋转、大小、转速、掉落速度控制、屏幕最大红包数量控制等功能

介绍

  1. 本文功能由canvas实现红包雨功能(index.tsx
  2. 本文为react的ts版。如有其他版本需求可评论区
  3. 观赏地址,需过墙
import React, { Component } from 'react';
// import './index.css';
import moneyx from '@/assets/images/RedEnvelopeRain/ball1.png';
import money1 from '@/assets/images/RedEnvelopeRain/money1.webp';
import money2 from '@/assets/images/pointCon/机器人.png';
import money3 from '@/assets/images/pointCon/无人机.png';
import {loadImage,positionX,randomRange,
} from './utils';
type minMax = [number, number];
const config = {// speed value areaspeedLimit: [1, 4] as minMax,// display quantitydensity: [5, 15] as minMax,imgInfo: {// image widthw: 50,// image heighth: 50,// image rotate value arearandomLimit: [0.5, 1] as minMax,},// image number max shownumberMaxLimit: 200,
};
const { speedLimit, imgInfo, numberMaxLimit, density } = config;export default class CanvasCom extends Component {// ratio = null;ctx: any = null;wid = 0;hei = 0;packedArr: ReturnType<typeof this.createPack>[] = [];// display quantitydensity = {min: density[0],max: density[1],};clearTime: any = null;img: any = [];loadingImageArr = [money1, moneyx, money2, money3]componentDidMount() {this.loadingImg();}loadingImg() {Promise.all(this.loadingImageArr.map(v => loadImage(v))).then((res) => {this.img = res;this.wid = window.innerWidth;this.hei = window.innerHeight;this.initCanvas();this.start();});}getPixelRatio = (context: any) => {const backingStore =context.backingStorePixelRatio ||context.webkitBackingStorePixelRatio ||context.mozBackingStorePixelRatio ||context.msBackingStorePixelRatio ||context.oBackingStorePixelRatio ||context.backingStorePixelRatio ||1;return (window.devicePixelRatio || 1) / backingStore;};initCanvas() {const canvas: HTMLCanvasElement | any = document.getElementById('canvas');canvas.width = this.wid;canvas.height = this.hei;if (canvas.getContext) {// 判断是否有此方法,如果有才能进入this.ctx = canvas.getContext('2d');// this.ratio = this.getPixelRatio(this.ctx);}}createPack() {const imgRandom = randomRange(...imgInfo.randomLimit);return {x: positionX(),y: 0,img: this.img[Math.floor(randomRange(0, this.loadingImageArr.length ))],// rotaterotate: randomRange(-45, 45),direction: Math.random(),speed: randomRange(...speedLimit),// rotate speedround: 0,roundSpeed: randomRange(1, 2),imgInfo: {w: imgInfo.w * imgRandom,h: imgInfo.h * imgRandom,},};}pushPackArr = () => {const { max, min } = this.density;const random = Math.floor(Math.random() * (max - min) + min);this.packedArr.push(...new Array(random).fill('').map(() => this.createPack()));this.clearTime = setTimeout(() => {if (this.packedArr.length > numberMaxLimit)return clearTimeout(this.clearTime);this.pushPackArr();}, 300);};drawPacked = () => {this.ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);this.packedArr.forEach((item, index) => {const r = ((item.rotate + item.round) * Math.PI) / 180;const temp = item.y - item.x * Math.tan(r);const top = temp * Math.cos(r);const left = item.x / Math.cos(r) + temp * Math.sin(r);this.ctx.save();this.ctx.rotate(r);this.ctx.drawImage(item.img,left - item.imgInfo.w / 2,top - item.imgInfo.h / 2,item.imgInfo.w,item.imgInfo.h);this.ctx.restore();if (item.direction < 0.5) {item.round -= item.roundSpeed;} else {item.round += item.roundSpeed;}if (item.y + item?.speed <= window.innerHeight) {item.y = item.y + item?.speed || 0;} else {// inititem.y = 0 + item?.speed || 0;item.x = positionX();Object.assign(item, this.createPack());}});window.requestAnimationFrame(this.drawPacked);};start = () => {this.pushPackArr();this.drawPacked();};render() {return (<div style={{ position: 'absolute', left: 0, top: 0, background: '#000' }}><canvas id="canvas"></canvas></div>);}
}
  1. utils/index.ts
export const loadImage = (url: string) => {if (!window?.Image) return null;return new Promise((resolve, reject) => {const img = new Image();img.src = url;img.onload = () => {resolve(img);};img.onerror = () => {reject(new Error('load image error!'));};});
};
export const positionX = () => Math.random() * window.innerWidth;
export const randomRange = (start: number, end: number) => {const random = (end - start) * Math.random() + start;const number = 1;const arr = new Array(number).fill('').map((v, i) => random / (i + 1));return arr[Math.floor(Math.random() * number)];
};

效果图

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

算水质TDS加温度补偿

先上图&#xff0c;就图里这款水质检测&#xff0c;用树莓派3/4的话&#xff0c;要配个温度检测作为温度校正&#xff0c;以及一个adc 元器件。我选ds18b20和ads1115。 再把模拟数据计算过程放一下&#xff1a; 温度检测元器件在农历钟那里提过&#xff0c;就是同款。此处先测个…

Android11 移植memtester压测内存

需求如题&#xff0c;从网上下载了memtest源码压缩包&#xff0c;准备放到系统源码编译&#xff0c;然后push到板子上执行&#xff0c;结果&#xff0c;编译出来一堆问题&#xff0c;报build err。 做如下代码改动&#xff1a; external/memtester-4.5.1/Android.mk | 16 exte…

机器学习基础之《回归与聚类算法(4)—逻辑回归与二分类(分类算法)》

一、什么是逻辑回归 1、逻辑回归&#xff08;Logistic Regression&#xff09;是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法&#xff0c;虽然名字中带有回归&#xff0c;但是它与回归之间有一定的联系。由于算法的简单和高效&#xff0c;在实际中应用非常广…

使用cpolar内网端口映射技术实现U8用友ERP本地部署的异地访问

文章目录 前言1. 服务器本机安装U8并调试设置2. 用友U8借助cpolar实现企业远程办公2.1 在被控端电脑上&#xff0c;点击开始菜单栏&#xff0c;打开设置——系统2.2 找到远程桌面2.3 启用远程桌面 3. 安装cpolar内网穿透3.1 注册cpolar账号3.2 下载cpolar客户端 4. 获取远程桌面…

NTFS磁盘格式读写工具Tuxera NTFS 2023 for Mac中文破解版v2023含最新激活序列号

Tuxera NTFS 2023 Mac 是一个NTFS文件系统驱动程序&#xff0c;为解决Mac上不能对NTFS格式硬盘进行访问和读写而生。实现苹果Mac OS X系统读写Microsoft Windows NTFS文件系统&#xff0c;在硬盘、U盘等外接设备中进行全面访问、删除、修改等相关操作。 tuxera ntfs 2023 破解…

Web架构安全分析/http/URL/Cookie攻击

Web 架构安全分析 Web 工作机制及基本概念 传统 Web 架构 LAMP 网页 概念 网页就是我们可以通过浏览器上网看到的精美页面&#xff0c;一般都是经过浏览器渲染过的 .html 页面&#xff0c;html 语言在浏览器中渲染。其中包含了CSS、JavaScript 等前端技术。通过浏览器访问…

24届好未来数开笔试

目录 选择、多选SQL题目描述输入 目标解答解析 题目分享 选择、多选 Java, int x 1, float y 2, x/y 0.5 2. Hive 的数据结构 基本数据类型 复合数据类型 text 不是 Hive 内外表 建表时如果不显示声明表的类型为 外表 Kafka 通过&#xff08;&#xff09;避免任务重复执行…

【技巧】如何设置Excel表只输入固定内容?

如果你需要在Excel表格中输入固定的内容&#xff0c;可以设置“限制录入内容”&#xff0c;这样就只能输入设置好的内容&#xff0c;避免不小心输入错误信息。下面来看看如何设置吧。 首先&#xff0c;打开Excel表格后&#xff0c;选中需要输入固定内容的表格区域。 比如图片…

Flutter笔记:发布一个Flutter头像模块 easy_avatar

Flutter笔记 发布一个头像Flutter模块 easy_avatar 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/1339…

利用PHP快速抓取音频数据的方法与技巧

目录 使用cURL库抓取音频数据 优点 潜在问题及解决方案 使用file_get_contents函数抓取音频数据 优点 潜在问题及解决方案 总结 随着互联网的发展&#xff0c;音频内容在网络上的应用越来越广泛&#xff0c;如音乐播放、语音通信等。有时&#xff0c;我们需要从特定的音…

ModStartCMS v7.4.0 公共图片库支持,安全功能升级

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 功能特性 丰富的模块市…

【Linux-常用命令-基础命令-删除文件夹以及内容-rm--r-命令-笔记】

【Linux-常用命令-基础命令-删除文件夹以及内容-rm--r-命令-笔记】 1、前言2、操作3、自己的操作 1、前言 最近&#xff0c;在使用Linux的时&#xff0c;使用相关基础命令是&#xff0c;总是容易忘记&#xff0c;上网一搜&#xff0c;大部分都写的比较繁琐&#xff0c;关于删除…

Python学习笔记——存储容器

食用说明&#xff1a;本笔记适用于有一定编程基础的伙伴们。希望有助于各位&#xff01; 列表 列表类似数组&#xff0c;其中可以包含不同类型的元素&#xff0c;写法如下&#xff1a; list1 [Google, Runoob, 1997, 2000] list2 [1, 2, 3, 4, 5 ] list3 ["a", …

Qt工具开发,该不该跳槽?

Qt工具开发&#xff0c;该不该跳槽? 就这样吧&#xff0c;我怕你跳不动。 嵌入式UI&#xff0c;目前趋势是向着LVGL发展。QT已经在淘汰期了。很多项目还在用&#xff0c;但技术上已经落后。QT短期内不会全面淘汰&#xff0c;但退位让贤的大趋势已经很清楚了。 最近很多小伙伴…

liunx下软链接和硬链接的用法

什么是软链接&#xff08;类似快捷方式&#xff09;&#xff1a; 符号连接&#xff08;Symbolic Link&#xff09;&#xff0c;也叫软连接。 软链接文件有类似于 Windows 的快捷方式。它实际上是一个特殊的文件。在符号连接中&#xff0c;文件实际上是一个文本文件&#xff0c…

嵌入式开发学习之STM32F407串口(USART)收发数据(三)

嵌入式开发学习之STM32F407串口&#xff08;USART&#xff09;收发数据&#xff08;三&#xff09; 开发涉及工具一、选定所使用的串口二、配置串口1.配置串口的I/O2.配置串口参数属性3.配置串口中断4.串口中断在哪里处理5.串口如何发送字符串 三、封装串口配置库文件1.创建头文…

【OpenVINO】OpenVINO C# API 常用 API 详解与演示

OpenVINO C# API 常用 API 详解与演示 1 安装OpenVINO C# API2 导入程序集 3 初始化OpenVINO 运行时内核4 加载并获取模型信息4.1 加载模型4.2 获取模型信息 5 编译模型并创建推理请求6 张量Tensor6.1 张量的获取与设置6.2 张量的信息获取与设置 7 加载推理数据7.1 获取输入张量…

循环日程安排问题(分治法)

函数接口定义&#xff1a; void Plan(int a[][N],int k); 裁判测试程序样例&#xff1a; #include #include <math.h> #include using namespace std; #define N 100 void Plan(int a[][N],int k); int main() { int i,j,a[N][N],k,size; cin>>k; sizepow(2,k)…

金山终端安全系统V9.0 SQL注入漏洞复现

0x01 产品简介 金山终端安全系统是一款为企业提供终端防护的安全产品&#xff0c;针对恶意软件、病毒和外部攻击提供防范措施&#xff0c;帮助维护企业数据和网络。 0x02 漏洞概述 金山终端安全系统V9.0 /inter/update_software_info_v2.php页面存在sql注入漏洞&#xff0c;该…

VsCode通过Git History插件查看某个页面的版本修改记录

首先需要安装插件Git History 方式一&#xff1a;通过 点击File History 查看某个文件变更&#xff1b;即通过commit的提交记录去查看某个文件的修改 方式二&#xff1a;通过点击选择toggle File Blame 查看当前页面每一行所有提交修改记录