- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ?
- module.exports = factory() :
- typeof define === 'function' && define.amd ? define(factory) :
- (global = typeof globalThis !== 'undefined' ? globalThis :
- global || self, global.mapboxgl1.RainfallEffect = factory());
- }(window,(function(){
- const createCanvas = id => {
- const canvasID ='rain-canvas' + id;
- let canvas = document.getElementById(canvasID);
- if(!canvas) canvas = document.createElement('canvas'),canvas.id = canvasID,document.body.append(canvas);
- canvas.style.width= '100%';
- canvas.style.height= '100%';
- canvas.style.position= 'absolute';
- canvas.style.zIndex=10;
- canvas.style.top= '0';
- canvas.style.left= '0';
- canvas.style.pointerEvents= 'none';
- return canvas;
- };
-
- // 雨滴类
- class Drop {
- constructor(x, y, speed, length, opacity,canvas) {
- this.x = x;
- this.y = y;
- this.speed = speed;
- this.length = length;
- this.opacity = opacity;
- this.canvas = canvas;
- }
-
- update() {
- this.y += this.speed;
- if (this.y > this.canvas.height) {
- this.y = 0 - this.length;
- }
- }
-
- draw() {
- let ctx = this.canvas.getContext('2d');
- ctx.beginPath();
- ctx.strokeStyle = `rgba(174,194,224,${this.opacity})`;
- ctx.lineWidth = 1;
- ctx.moveTo(this.x, this.y);
- ctx.lineTo(this.x, this.y + this.length);
- ctx.stroke();
- }
- }
-
- function createRain(level,canvas) {
- let drops = [];
- let rainDensity, rainSpeed, rainLength;
-
- switch (level) {
- case '1': // 小雨
- rainDensity = 100;
- rainSpeed = [1, 2];
- rainLength = [5, 10];
- break;
- case '2': // 中雨
- rainDensity = 200;
- rainSpeed = [2, 3];
- rainLength = [10, 15];
- break;
- case '3': // 大雨
- rainDensity = 300;
- rainSpeed = [3, 4];
- rainLength = [15, 20];
- break;
- }
-
- for (let i = 0; i < rainDensity; i++) {
- const x = Math.random() * canvas.width;
- const y = Math.random() * canvas.height;
- const speed = Math.random() * (rainSpeed[1] - rainSpeed[0]) + rainSpeed[0];
- const length = Math.random() * (rainLength[1] - rainLength[0]) + rainLength[0];
- const opacity = Math.random() * 0.5 + 0.5;
- drops.push(new Drop(x, y, speed, length, opacity,canvas));
- }
-
- return drops
- }
-
- function animateRain(drops,lightningTimer,flashOpacity,canvas) {
- let ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- drops.forEach(drop => {
- drop.update();
- drop.draw();
- });
-
- // 控制闪电效果
- if (lightningTimer <= 0 && false) {
- if (Math.random() > 0.98) { // 设置闪电随机出现的概率
- lightningTimer = Math.random() * 30 + 10; // 控制闪电持续的帧数
- flashOpacity = 1; // 闪电时的屏幕亮度
- createLightning(canvas); // 生成闪电
- }
- } else {
- lightningTimer--;
- flashOpacity -= 0.05; // 闪电逐渐消失
- }
-
- // 绘制闪电的亮光效果
- if (flashOpacity > 0) {
- ctx.fillStyle = `rgba(255, 255, 255, ${flashOpacity})`;
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- }
-
- return requestAnimationFrame(()=> animateRain(drops,lightningTimer,flashOpacity,canvas));
- }
-
- // 生成闪电
- function createLightning(canvas) {
- let ctx = canvas.getContext('2d');
- const lightningX = Math.random() * canvas.width; // 闪电的横向位置
- const lightningY = Math.random() * (canvas.height / 2); // 闪电的起点(从屏幕上半部分)
- ctx.strokeStyle = 'rgba(255, 255, 255, 1)';
- ctx.lineWidth = 2;
-
- // 生成多个随机折线段构成闪电
- let x = lightningX;
- let y = lightningY;
-
- for (let i = 0; i < 10; i++) {
- let nextX = x + (Math.random() * 80 - 40); // 随机向左或向右偏移
- let nextY = y + (Math.random() * 80 + 20); // 向下移动
-
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(nextX, nextY);
- ctx.stroke();
-
- x = nextX;
- y = nextY;
-
- if (y > canvas.height) break; // 闪电到达屏幕底部结束
- }
- }
-
-
- function resizeCanvas(canvas) {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- }
-
- return class RainfallEffect {
- canvas = null;
- animateId = null;
- drops = [];
- rainLevel = 'light';
- lightningTimer = 0;
- flashOpacity = 0;
- level = 1;
- constructor(props) {
- let canvas = createCanvas(1);
- this.canvas = canvas;
- window.addEventListener('resize', () => resizeCanvas(canvas));
- }
-
- rain(level){
- this.level = level;
- this.drops = createRain(this.level,this.canvas);
- if(this.animateId) cancelAnimationFrame(this.animateId);
- this.animateId = animateRain(this.drops,this.lightningTimer,this.flashOpacity,this.canvas);
- }
-
- hide(){
- this.canvas.style.display = 'none';
- }
-
- show(){
- this.canvas.style.display = 'block';
- }
-
- destroy(){
- if(this.animateId) cancelAnimationFrame(this.animateId);
- if(this.canvas) this.canvas.remove();
- }
- }
- })));