UNPKG

@ahmiao666/red-packet-rain-react

Version:
12 lines (11 loc) 31.8 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).RedPacketRainReact={},e.React)}(this,function(e,t){"use strict";const i={containerWidth:"100%",containerHeight:"100%",count:20,density:5,speed:{min:2,max:6},size:{width:60,height:80},rotation:!0,rotationSpeed:{min:-.02,max:.02},enablePerformanceMode:!0,maxFPS:60,qualityMaxFPS:144,clickEffect:!0,isParticle:!0};class a{constructor(e,t){this.redPackets=[],this.animationId=null,this.isRunning=!1,this.isPaused=!1,this.lastFrameTime=0,this.frameCount=0,this.lastFpsTime=0,this.currentFPS=0,this.lastSpawnTime=0,this.actualWidth=800,this.actualHeight=600,this.redPacketPool=[],this.poolSize=50,this.redPacketDataIndex=0,this.stats={totalCollected:0,totalValue:0,fps:0},this.redPacketImage=null,this.lastClickTime=0,this.clickDebounceDelay=100,this.debugClicks=[],this.particles=[],this.particlePool=[],this.particlePoolSize=100,this.particleConfig={count:15,speed:{min:2,max:8},size:{min:3,max:8},life:{min:800,max:1500},colors:["#FF6B6B"],gravity:.3,friction:.98,spread:2*Math.PI},this.canvas=e,this.ctx=e.getContext("2d"),this.config={...i,...t},this.optimizeConfig(),this.resizeCanvas(),this.initializePool(),this.initializeParticlePool(),this.bindEvents(),this.loadRedPacketImage()}initializePool(){for(let e=0;e<this.poolSize;e++)this.redPacketPool.push(this.createRedPacket())}initializeParticlePool(){for(let e=0;e<this.particlePoolSize;e++)this.particlePool.push(this.createParticle())}createParticle(){return{id:Math.random().toString(36).slice(2,11),x:0,y:0,vx:0,vy:0,size:5,opacity:1,color:"#FFD700",life:1,maxLife:1e3,gravity:.3,friction:.98,rotation:0,rotationSpeed:0}}getParticleFromPool(){return this.particlePool.pop()||this.createParticle()}returnParticleToPool(e){this.particlePool.length<this.particlePoolSize&&this.particlePool.push(e)}resetParticle(e,t,i){const a=this.particleConfig,n=Math.random()*a.spread,r=a.speed.min+Math.random()*(a.speed.max-a.speed.min);e.x=t,e.y=i,e.vx=Math.cos(n)*r,e.vy=Math.sin(n)*r-2*Math.random(),e.size=a.size.min+Math.random()*(a.size.max-a.size.min),e.initialSize=void 0,e.opacity=1,e.color=a.colors[Math.floor(Math.random()*a.colors.length)],e.maxLife=a.life.min+Math.random()*(a.life.max-a.life.min),e.life=e.maxLife,e.gravity=a.gravity,e.friction=a.friction,e.rotation=Math.random()*Math.PI*2,e.rotationSpeed=.2*(Math.random()-.5)}getRedPacketFromPool(){const e=this.redPacketPool.pop()||this.createRedPacket();return this.resetRedPacket(e),e}returnRedPacketToPool(e){this.redPacketPool.length<this.poolSize&&this.redPacketPool.push(e)}getRedPacketData(){if(!this.config.redPackets||"number"==typeof this.config.redPackets)return null;if(Array.isArray(this.config.redPackets)&&this.config.redPackets.length>0){const e=this.config.redPackets[this.redPacketDataIndex];return this.redPacketDataIndex=(this.redPacketDataIndex+1)%this.config.redPackets.length,e}return null}isSpecialRedPacket(e){return!!this.config.isSpecialFn&&("function"==typeof this.config.isSpecialFn?this.config.isSpecialFn(e):"string"==typeof this.config.isSpecialFn&&Boolean(e[this.config.isSpecialFn]))}createRedPacket(){const e=this.getRedPacketData(),t={id:Math.random().toString(36).slice(2,11),x:0,y:0,width:this.config.size.width,height:this.config.size.height,speed:0,rotation:0,rotationSpeed:0,scale:1,opacity:1,collected:!1,value:Math.floor(100*Math.random())+1,type:"normal",originalData:null};return e&&this.isUsingArrayMode()?(t.id=e.id||t.id,t.value=e.value||t.value,t.type=this.isSpecialRedPacket(e)?"special":"normal",t.originalData=e):(t.type="normal",t.originalData=null),t}resetRedPacket(e){const t=this.getRedPacketData();e.x=Math.random()*(this.actualWidth-this.config.size.width),e.y=-this.config.size.height,e.speed=Number(this.config.speed.min)+Math.random()*(Number(this.config.speed.max)-Number(this.config.speed.min)),e.rotation=0,e.rotationSpeed=this.config.rotation?this.config.rotationSpeed.min+Math.random()*(this.config.rotationSpeed.max-this.config.rotationSpeed.min):0,e.scale=.8+.4*Math.random(),e.opacity=1,e.collected=!1,t&&this.isUsingArrayMode()?(e.id=t.id||e.id,e.value=t.value||Math.floor(100*Math.random())+1,e.type=this.isSpecialRedPacket(t)?"special":"normal",e.originalData=t):(e.value=Math.floor(100*Math.random())+1,e.type="normal",e.originalData=null)}optimizeConfig(){this.config.redPackets&&Array.isArray(this.config.redPackets)&&this.config.redPackets.length>0?this.config.count=this.config.redPackets.length:(void 0===this.config.count||null===this.config.count||this.config.count<=0)&&(this.config.count=20)}isUsingArrayMode(){return!!(this.config.redPackets&&Array.isArray(this.config.redPackets)&&this.config.redPackets.length>0)}loadRedPacketImage(){this.config.redPacketImage&&("string"==typeof this.config.redPacketImage?(this.redPacketImage=new Image,this.redPacketImage.src=this.config.redPacketImage):this.redPacketImage=this.config.redPacketImage)}resizeCanvas(){let e=800,t=600;if("string"==typeof this.config.containerWidth&&this.config.containerWidth.includes("%")){const t=this.canvas.parentElement;t&&(e=t.clientWidth*parseFloat(this.config.containerWidth)/100)}else e="number"==typeof this.config.containerWidth?this.config.containerWidth:800;if("string"==typeof this.config.containerHeight&&this.config.containerHeight.includes("%")){const e=this.canvas.parentElement;e&&(t=e.clientHeight*parseFloat(this.config.containerHeight)/100)}else t="number"==typeof this.config.containerHeight?this.config.containerHeight:600;this.canvas.width=this.actualWidth=Math.max(100,Math.min(e,4e3)),this.canvas.height=this.actualHeight=Math.max(100,Math.min(t,4e3))}bindEvents(){this.canvas.addEventListener("click",this.handleClick.bind(this)),this.canvas.addEventListener("touchstart",this.handleTouch.bind(this)),window.addEventListener("resize",this.handleResize.bind(this))}handleClick(e){const t=this.getCanvasCoordinates(e.clientX,e.clientY);this.checkCollision(t.x,t.y,"mouse")}handleTouch(e){e.preventDefault();const t=e.touches[0],i=this.getCanvasCoordinates(t.clientX,t.clientY);this.checkCollision(i.x,i.y,"touch")}getCanvasCoordinates(e,t){const i=this.canvas.getBoundingClientRect(),a=i.width,n=i.height,r=this.canvas.width/a,o=this.canvas.height/n,s=(e-i.left)*r,c=(t-i.top)*o;return this.config.debugMode&&console.log(`🎯 点击坐标转换:\n 客户端坐标: (${e}, ${t})\n Canvas矩形: ${JSON.stringify(i)}\n 缩放比例: (${r.toFixed(3)}, ${o.toFixed(3)})\n 最终坐标: (${s.toFixed(1)}, ${c.toFixed(1)})`),{x:s,y:c}}handleResize(){this.resizeCanvas()}checkCollision(e,t,i="mouse"){const a=Date.now();if(a-this.lastClickTime<this.clickDebounceDelay)return void(this.config.debugMode&&console.log(`🎯 点击被防抖过滤 (间隔: ${a-this.lastClickTime}ms)`));this.lastClickTime=a,this.config.debugMode&&console.log(`🎯 检查碰撞: (${e.toFixed(1)}, ${t.toFixed(1)}) [${i}]`);let n=!1;for(let i=this.redPackets.length-1;i>=0;i--){const a=this.redPackets[i];if(this.isPointInRedPacket(e,t,a)){this.config.debugMode&&console.log(`🎯 命中红包: ${a.id}, 类型: ${a.type}, 价值: ${a.value}`),this.collectRedPacket(a,e,t),this.redPackets.splice(i,1),this.returnRedPacketToPool(a),n=!0;break}}this.config.debugMode&&(this.debugClicks.push({x:e,y:t,time:a,hit:n}),n||(console.log(`🎯 未命中任何红包 - 当前红包数量: ${this.redPackets.length}`),this.redPackets.slice(0,3).forEach((i,a)=>{const n=i.x+i.width/2,r=i.y+i.height/2,o=Math.sqrt((e-n)**2+(t-r)**2);console.log(`红包${a+1}: 中心(${n.toFixed(1)}, ${r.toFixed(1)}), 距离: ${o.toFixed(1)}`)})))}isPointInRedPacket(e,t,i){const a=i.x+i.width/2,n=i.y+i.height/2,r=i.width*i.scale,o=i.height*i.scale,s=r+.1*r,c=o+.1*o,l=e>=a-s/2&&e<=a+s/2&&t>=n-c/2&&t<=n+c/2;return this.config.debugMode&&l&&console.log(`🎯 红包边界检测:\n 红包中心: (${a.toFixed(1)}, ${n.toFixed(1)})\n 原始尺寸: ${r.toFixed(1)} x ${o.toFixed(1)}\n 扩展尺寸: ${s.toFixed(1)} x ${c.toFixed(1)}\n 点击坐标: (${e.toFixed(1)}, ${t.toFixed(1)})\n 距离中心: (${Math.abs(e-a).toFixed(1)}, ${Math.abs(t-n).toFixed(1)})`),l}collectRedPacket(e,t,i){e.collected=!0,this.stats.totalCollected++,this.stats.totalValue+=e.value,!this.config.enablePerformanceMode&&this.config.isParticle&&this.createRedPacketParticles(e,t,i),this.onRedPacketClickCallback&&this.onRedPacketClickCallback({redPacket:e,x:t,y:i,value:e.value})}createRedPacketParticles(e,t,i){const a=this.particleConfig.count,n="special"===e.type?1.5*a:a;for(let a=0;a<n;a++){const a=this.getParticleFromPool();this.resetParticle(a,t,i),"special"===e.type&&(a.color="#FFD700",a.size*=1.3),this.particles.push(a)}this.config.debugMode&&console.log(`🎆 创建了 ${n} 个粒子 [红包类型: ${e.type}]`)}updateParticles(e){const t=e/16.67;for(let i=this.particles.length-1;i>=0;i--){const a=this.particles[i];a.x+=a.vx*t,a.y+=a.vy*t,a.vy+=a.gravity*t,a.vx*=a.friction,a.vy*=a.friction,a.rotation+=a.rotationSpeed*t,a.life-=e;const n=Math.max(0,a.life/a.maxLife);a.opacity=n,a.initialSize||(a.initialSize=a.size);const r=.3+.7*n;a.size=a.initialSize*r,(a.life<=0||a.y>this.actualHeight+50)&&(this.particles.splice(i,1),this.returnParticleToPool(a))}}renderParticles(){const e=this.ctx;for(const t of this.particles){e.save(),e.globalAlpha=t.opacity,e.translate(t.x,t.y),e.rotate(t.rotation);const i=e.createRadialGradient(0,0,0,0,0,t.size);i.addColorStop(0,t.color),i.addColorStop(.7,t.color+"80"),i.addColorStop(1,t.color+"00"),e.fillStyle=i,e.beginPath(),e.arc(0,0,t.size,0,2*Math.PI),e.fill(),"#FFD700"!==t.color||this.config.enablePerformanceMode||(e.shadowColor=t.color,e.shadowBlur=2*t.size,e.beginPath(),e.arc(0,0,.5*t.size,0,2*Math.PI),e.fill()),e.restore()}}spawnRedPacket(){const e=Date.now(),t=1e3/this.config.density;if(e-this.lastSpawnTime>t&&this.redPackets.length<this.config.count){const t=this.getRedPacketFromPool();this.redPackets.push(t),this.lastSpawnTime=e}}updateRedPackets(e){for(let t=this.redPackets.length-1;t>=0;t--){const i=this.redPackets[t];i.y+=i.speed*(e/16.67),this.config.rotation&&(i.rotation+=i.rotationSpeed*(e/16.67)),i.y>this.actualHeight&&(this.redPackets.splice(t,1),this.returnRedPacketToPool(i))}}renderRedPackets(){this.ctx.clearRect(0,0,this.actualWidth,this.actualHeight),this.config.customStyles?.backgroundColor&&(this.ctx.fillStyle=this.config.customStyles.backgroundColor,this.ctx.fillRect(0,0,this.actualWidth,this.actualHeight));for(const e of this.redPackets)this.renderRedPacket(e)}renderRedPacket(e){const t=this.ctx,i=e.x+e.width/2,a=e.y+e.height/2;t.save(),t.globalAlpha=e.opacity,t.translate(i,a),this.config.rotation&&t.rotate(e.rotation),t.scale(e.scale,e.scale),this.config.enablePerformanceMode||"special"!==e.type||(t.shadowColor="#FFD700",t.shadowBlur=10),this.redPacketImage?t.drawImage(this.redPacketImage,-e.width/2,-e.height/2,e.width,e.height):this.drawDefaultRedPacket(t,e),t.restore()}drawDefaultRedPacket(e,t){const i=t.width,a=t.height;e.fillStyle="special"===t.type?"#FFD700":"#FF6B6B",e.fillRect(-i/2,-a/2,i,a),e.strokeStyle=this.config.customStyles?.borderColor||"#FF4444",e.lineWidth=2,e.strokeRect(-i/2,-a/2,i,a),e.fillStyle="#FFFFFF",e.font="20px Arial",e.textAlign="center",e.textBaseline="middle",e.fillText("¥",0,-5),t.value&&(e.font="10px Arial",e.fillText(t.value.toString(),0,8))}animate(e){if(!this.isRunning||this.isPaused)return;const t=1e3/(this.config.enablePerformanceMode?this.config.maxFPS:this.config.qualityMaxFPS||144),i=e-this.lastFrameTime;i<.9*t||(this.lastFrameTime=e,this.updateFPS(e),this.spawnRedPacket(),this.updateRedPackets(i),this.updateParticles(i),this.renderRedPackets(),this.renderParticles(),this.config.debugMode&&this.renderDebugInfo(),this.triggerCallbacks()),this.isRunning&&!this.isPaused&&(this.animationId=requestAnimationFrame(this.animate.bind(this)))}updateFPS(e){this.frameCount++,e-this.lastFpsTime>=1e3&&(this.stats.fps=this.frameCount,this.frameCount=0,this.lastFpsTime=e)}renderDebugInfo(){const e=this.ctx;e.save(),e.fillStyle="rgba(0, 0, 0, 0.8)",e.fillRect(10,10,300,120),e.fillStyle="#00FF00",e.font="14px Arial",e.textAlign="left",e.fillText(`FPS: ${this.stats.fps}`,15,30),e.fillText(`红包数量: ${this.redPackets.length}`,15,50),e.fillText(`粒子数量: ${this.particles.length}`,15,70),e.fillText(`Canvas尺寸: ${this.actualWidth}x${this.actualHeight}`,15,90),e.fillText(`点击记录: ${this.debugClicks.length}`,15,110);for(const t of this.redPackets){const i=t.x+t.width/2,a=t.y+t.height/2,n=t.width*t.scale,r=t.height*t.scale,o=n+.1*n,s=r+.1*r;e.strokeStyle="rgba(255, 0, 0, 0.5)",e.lineWidth=1,e.strokeRect(i-n/2,a-r/2,n,r),e.strokeStyle="rgba(0, 255, 0, 0.7)",e.lineWidth=2,e.strokeRect(i-o/2,a-s/2,o,s),e.fillStyle="rgba(0, 255, 255, 0.8)",e.fillRect(i-2,a-2,4,4)}const t=Date.now();for(const i of this.debugClicks){const a=t-i.time;if(a<2e3){const t=Math.max(0,1-a/2e3);e.fillStyle=i.hit?`rgba(0, 255, 0, ${t})`:`rgba(255, 0, 0, ${t})`,e.fillRect(i.x-5,i.y-5,10,10),e.strokeStyle=i.hit?`rgba(0, 255, 0, ${t})`:`rgba(255, 0, 0, ${t})`,e.lineWidth=2,e.beginPath(),e.arc(i.x,i.y,15,0,2*Math.PI),e.stroke()}}e.restore()}triggerCallbacks(){this.onAnimationStateChangeCallback&&this.onAnimationStateChangeCallback({isRunning:this.isRunning,isPaused:this.isPaused,totalCollected:this.stats.totalCollected,currentRedPackets:[...this.redPackets],fps:this.stats.fps}),this.onPerformanceUpdateCallback&&this.onPerformanceUpdateCallback({fps:this.stats.fps,renderTime:0,updateTime:0,totalRedPackets:this.stats.totalCollected,activeRedPackets:this.redPackets.length})}start(){this.isRunning||(this.isRunning=!0,this.isPaused=!1,this.lastFrameTime=performance.now(),this.animate(this.lastFrameTime))}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}pause(){this.isPaused=!0}resume(){this.isPaused&&this.isRunning&&(this.isPaused=!1,this.lastFrameTime=performance.now(),this.animate(this.lastFrameTime))}clear(){this.redPackets.forEach(e=>this.returnRedPacketToPool(e)),this.redPackets=[],this.particles.forEach(e=>this.returnParticleToPool(e)),this.particles=[],this.ctx.clearRect(0,0,this.actualWidth,this.actualHeight),this.stats.totalCollected=0,this.stats.totalValue=0}updateConfig(e){this.config={...this.config,...e},this.optimizeConfig(),this.resizeCanvas(),e.redPacketImage&&this.loadRedPacketImage(),e.redPackets&&(this.redPacketDataIndex=0)}getStats(){return{fps:this.stats.fps,renderTime:0,updateTime:0,totalRedPackets:this.stats.totalCollected,activeRedPackets:this.redPackets.length}}getCollectionStats(){return{totalCollected:this.stats.totalCollected,totalValue:this.stats.totalValue}}setPerformanceMode(e){this.config.enablePerformanceMode=e}getPerformanceMode(){return this.config.enablePerformanceMode}onRedPacketClick(e){this.onRedPacketClickCallback=e}onAnimationStateChange(e){this.onAnimationStateChangeCallback=e}onPerformanceUpdate(e){this.onPerformanceUpdateCallback=e}setParticleConfig(e){this.particleConfig={...this.particleConfig,...e}}getParticleConfig(){return{...this.particleConfig}}destroy(){this.stop(),this.clear(),this.debugClicks=[],this.lastClickTime=0,this.particlePool=[],this.canvas.removeEventListener("click",this.handleClick.bind(this)),this.canvas.removeEventListener("touchstart",this.handleTouch.bind(this)),window.removeEventListener("resize",this.handleResize.bind(this))}}var n,r={exports:{}},o={};var s,c={}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */"production"===process.env.NODE_ENV?r.exports=function(){if(n)return o;n=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function i(t,i,a){var n=null;if(void 0!==a&&(n=""+a),void 0!==i.key&&(n=""+i.key),"key"in i)for(var r in a={},i)"key"!==r&&(a[r]=i[r]);else a=i;return i=a.ref,{$$typeof:e,type:t,key:n,ref:void 0!==i?i:null,props:a}}return o.Fragment=t,o.jsx=i,o.jsxs=i,o}():r.exports=(s||(s=1,"production"!==process.env.NODE_ENV&&function(){function e(t){if(null==t)return null;if("function"==typeof t)return t.$$typeof===R?null:t.displayName||t.name||null;if("string"==typeof t)return t;switch(t){case g:return"Fragment";case p:return"Profiler";case m:return"StrictMode";case k:return"Suspense";case x:return"SuspenseList";case S:return"Activity"}if("object"==typeof t)switch("number"==typeof t.tag&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),t.$$typeof){case f:return"Portal";case y:return(t.displayName||"Context")+".Provider";case P:return(t._context.displayName||"Context")+".Consumer";case b:var i=t.render;return(t=t.displayName)||(t=""!==(t=i.displayName||i.name||"")?"ForwardRef("+t+")":"ForwardRef"),t;case C:return null!==(i=t.displayName||null)?i:e(t.type)||"Memo";case v:i=t._payload,t=t._init;try{return e(t(i))}catch(e){}}return null}function i(e){return""+e}function a(e){try{i(e);var t=!1}catch(e){t=!0}if(t){var a=(t=console).error,n="function"==typeof Symbol&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return a.call(t,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",n),i(e)}}function n(t){if(t===g)return"<>";if("object"==typeof t&&null!==t&&t.$$typeof===v)return"<...>";try{var i=e(t);return i?"<"+i+">":"<...>"}catch(e){return"<...>"}}function r(){return Error("react-stack-top-frame")}function o(){var t=e(this.type);return T[t]||(T[t]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),void 0!==(t=this.props.ref)?t:null}function s(t,i,n,r,s,c,h,f){var g,m=i.children;if(void 0!==m)if(r)if(w(m)){for(r=0;r<m.length;r++)l(m[r]);Object.freeze&&Object.freeze(m)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else l(m);if(M.call(i,"key")){m=e(t);var p=Object.keys(i).filter(function(e){return"key"!==e});r=0<p.length?"{key: someKey, "+p.join(": ..., ")+": ...}":"{key: someKey}",I[m+r]||(p=0<p.length?"{"+p.join(": ..., ")+": ...}":"{}",console.error('A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',r,m,p,m),I[m+r]=!0)}if(m=null,void 0!==n&&(a(n),m=""+n),function(e){if(M.call(e,"key")){var t=Object.getOwnPropertyDescriptor(e,"key").get;if(t&&t.isReactWarning)return!1}return void 0!==e.key}(i)&&(a(i.key),m=""+i.key),"key"in i)for(var P in n={},i)"key"!==P&&(n[P]=i[P]);else n=i;return m&&function(e,t){function i(){d||(d=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",t))}i.isReactWarning=!0,Object.defineProperty(e,"key",{get:i,configurable:!0})}(n,"function"==typeof t?t.displayName||t.name||"Unknown":t),function(e,t,i,a,n,r,s,c){return i=r.ref,e={$$typeof:u,type:e,key:t,props:r,_owner:n},null!==(void 0!==i?i:null)?Object.defineProperty(e,"ref",{enumerable:!1,get:o}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:s}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:c}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}(t,m,c,0,null===(g=F.A)?null:g.getOwner(),n,h,f)}function l(e){"object"==typeof e&&null!==e&&e.$$typeof===u&&e._store&&(e._store.validated=1)}var d,h=t,u=Symbol.for("react.transitional.element"),f=Symbol.for("react.portal"),g=Symbol.for("react.fragment"),m=Symbol.for("react.strict_mode"),p=Symbol.for("react.profiler"),P=Symbol.for("react.consumer"),y=Symbol.for("react.context"),b=Symbol.for("react.forward_ref"),k=Symbol.for("react.suspense"),x=Symbol.for("react.suspense_list"),C=Symbol.for("react.memo"),v=Symbol.for("react.lazy"),S=Symbol.for("react.activity"),R=Symbol.for("react.client.reference"),F=h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,M=Object.prototype.hasOwnProperty,w=Array.isArray,j=console.createTask?console.createTask:function(){return null},T={},$=(h={"react-stack-bottom-frame":function(e){return e()}})["react-stack-bottom-frame"].bind(h,r)(),z=j(n(r)),I={};c.Fragment=g,c.jsx=function(e,t,i,a,r){var o=1e4>F.recentlyCreatedOwnerStacks++;return s(e,t,i,!1,0,r,o?Error("react-stack-top-frame"):$,o?j(n(e)):z)},c.jsxs=function(e,t,i,a,r){var o=1e4>F.recentlyCreatedOwnerStacks++;return s(e,t,i,!0,0,r,o?Error("react-stack-top-frame"):$,o?j(n(e)):z)}}()),c);var l=r.exports;const d={card:{background:"#f8f9fa",borderRadius:"8px",padding:"20px",marginBottom:"20px"},whiteCard:{textAlign:"center",padding:"15px",background:"white",borderRadius:"6px",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.1)"},grid:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(200px, 1fr))",gap:"20px"}},h={container:{...d.card,...d.grid},statItem:d.whiteCard,statValue:{fontSize:"2em",fontWeight:"bold",color:"#ff6b6b"},statLabel:{color:"#666",marginTop:"5px"},modeValue:{fontSize:"1.2em",fontWeight:"bold",color:"#ff6b6b"}},u={container:{marginBottom:"20px",display:"flex",gap:"10px",flexWrap:"wrap"},base:{padding:"12px 24px",border:"none",borderRadius:"25px",fontSize:"16px",fontWeight:"600",cursor:"pointer",transition:"all 0.3s ease",boxShadow:"0 4px 15px rgba(0, 0, 0, 0.2)",margin:"5px"},primary:{background:"linear-gradient(45deg, #ff6b6b, #ffa500)",color:"white"},secondary:{background:"#6c757d",color:"white"}},f={container:d.card,title:{margin:"0 0 20px 0",color:"#ff6b6b"},configItem:{display:"flex",alignItems:"center",gap:"10px",marginBottom:"15px"},label:{minWidth:"80px",fontWeight:"600",color:"#333"},slider:{flex:1,height:"6px",background:"#ddd",borderRadius:"3px",outline:"none",appearance:"none"},value:{minWidth:"30px",textAlign:"center",fontWeight:"bold",color:"#ff6b6b"}},g={container:{background:"linear-gradient(135deg, #e8f4f8 0%, #d4e6f1 100%)",borderRadius:"8px",padding:"25px",marginTop:"20px"},title:{color:"#2c3e50",marginTop:0},list:{paddingLeft:"20px"},listItem:{marginBottom:"8px",color:"#34495e"}},m={display:"block",width:"100%",height:"100%"},p=e=>({width:"100%",height:"400px",overflow:"hidden",...e}),P=({value:e,label:t,isMode:i=!1})=>l.jsxs("div",{style:h.statItem,children:[l.jsx("div",{style:i?h.modeValue:h.statValue,children:e}),l.jsx("div",{style:h.statLabel,children:t})]}),y=({stats:e})=>l.jsxs("div",{style:h.container,children:[l.jsx(P,{value:e.fps,label:"FPS"}),l.jsx(P,{value:e.collected,label:"已收集"}),l.jsx(P,{value:`¥${e.totalValue}`,label:"总价值"}),l.jsx(P,{value:e.activeCount,label:"活跃红包"}),l.jsx(P,{value:e.performanceMode,label:"当前模式",isMode:!0})]}),b=({onClick:e,children:t,isPrimary:i=!1})=>{const a={...u.base,...i?u.primary:u.secondary};return l.jsx("button",{style:a,onClick:e,children:t})},k=({onStart:e,onStop:t,onPause:i,onResume:a,onClear:n,onToggleDebug:r,onTogglePerformance:o,onToggleFrameLimit:s,isPerformanceMode:c,isDebugMode:d,isFrameLimitEnabled:h})=>l.jsxs("div",{style:u.container,children:[l.jsx(b,{onClick:e,isPrimary:!0,children:"🚀 开始"}),l.jsx(b,{onClick:t,children:"⏹️ 停止"}),l.jsx(b,{onClick:i,children:"⏸️ 暂停"}),l.jsx(b,{onClick:a,children:"▶️ 继续"}),l.jsx(b,{onClick:n,children:"🧹 清空"}),l.jsxs(b,{onClick:r,isPrimary:d,children:["🐛 ",d?"关闭调试":"调试模式"]}),l.jsxs(b,{onClick:o,isPrimary:c,children:["⚡ ",c?"高质量模式":"性能模式"]}),l.jsxs(b,{onClick:s,isPrimary:h,children:["🎯 ",h?"关闭限制":"启用限制"]})]}),x=({label:e,value:t,min:i,max:a,onChange:n})=>l.jsxs("div",{style:f.configItem,children:[l.jsx("label",{style:f.label,children:e}),l.jsx("input",{style:f.slider,type:"range",min:i,max:a,value:t,onChange:e=>n(parseInt(e.target.value))}),l.jsx("span",{style:f.value,children:t})]}),C=({config:e,onConfigChange:t})=>l.jsxs("div",{style:f.container,children:[l.jsx("h3",{style:f.title,children:"⚙️ 配置调整"}),l.jsx(x,{label:"红包数量",value:e.count||15,min:5,max:50,onChange:e=>t("count",e)}),l.jsx(x,{label:"红包密度",value:e.density||3,min:1,max:10,onChange:e=>t("density",e)}),l.jsx(x,{label:"最小速度",value:e.speed?.min||2,min:1,max:5,onChange:e=>t("minSpeed",e)}),l.jsx(x,{label:"最大速度",value:e.speed?.max||5,min:3,max:10,onChange:e=>t("maxSpeed",e)}),l.jsx(x,{label:"高质量帧率",value:e.qualityMaxFPS||144,min:60,max:240,onChange:e=>t("qualityMaxFPS",e)})]}),v=()=>l.jsxs("div",{style:g.container,children:[l.jsx("h3",{style:g.title,children:"📖 使用说明"}),l.jsx("ul",{style:g.list,children:["🎯 点击红包进行收集,每个红包都有随机的价值","⚡ 金色红包为特殊红包,价值更高","🎛️ 使用滑块实时调整红包参数","📊 观察FPS和性能统计","🔍 性能模式:简化渲染、60FPS限制、对象池复用","🎨 高质量模式:完整视觉效果、144FPS限制、对象池复用","🖥️ 帧率受显示器刷新率限制,会自动检测并调整"].map((e,t)=>l.jsx("li",{style:g.listItem,children:e},t))})]}),{useState:S,useCallback:R}=t,F={count:15,density:3,speed:{min:2,max:5},maxFPS:60,qualityMaxFPS:144,enablePerformanceMode:!0,enableFrameRateLimit:!0,debugMode:!1},{useCallback:M,useEffect:w}=t,j=e=>{if(!e)return{width:800,height:400};const t=e.getBoundingClientRect();return{width:t.width||800,height:t.height||400}},{useRef:T,useEffect:$,useCallback:z}=t,I=(e,i,n=!0,r,o,s)=>{const c=t.useRef(null),l=t.useRef(!1),d=t.useRef(i);t.useEffect(()=>{d.current=i,c.current&&l.current&&c.current.updateConfig(i)},[i]);const h=z(()=>{if(e.current&&!c.current&&!l.current){const t=e.current,i=t.parentElement;requestAnimationFrame(()=>{if(i&&!c.current){const{width:e,height:h}=j(i);console.log(`📐 Canvas容器尺寸: ${e}x${h}px`);const u={containerWidth:e,containerHeight:h,count:15,density:3,speed:{min:2,max:5},maxFPS:60,qualityMaxFPS:144,enablePerformanceMode:!0,enableFrameRateLimit:!0,debugMode:!1,...d.current};c.current=new a(t,u),r&&c.current.onRedPacketClick(r),o&&c.current.onAnimationStateChange(o),s&&c.current.onPerformanceUpdate(s),l.current=!0,setTimeout(()=>{(e=>{let t=0;const i=performance.now(),a=n=>{if(t++,n-i>=1e3){const i=t;console.log(`当前显示器刷新率: ${i}Hz`),e&&e(i)}else requestAnimationFrame(a)};requestAnimationFrame(a)})()},1e3),n&&(console.log("🎬 自动启动红包雨"),c.current.start());const f=()=>{if(c.current&&i){const e=j(i);c.current.updateConfig({containerWidth:e.width,containerHeight:e.height})}};window.addEventListener("resize",f);const g=()=>{window.removeEventListener("resize",f)};c.current.cleanup=g}})}},[e,n,r,o,s]),u=z(()=>{c.current&&(c.current.cleanup&&c.current.cleanup(),c.current.destroy(),c.current=null,l.current=!1)},[]),f=z(()=>{c.current&&c.current.start()},[]),g=z(()=>{c.current&&c.current.stop()},[]),m=z(()=>{c.current&&c.current.pause()},[]),p=z(()=>{c.current&&c.current.resume()},[]),P=z(()=>{c.current&&c.current.clear()},[]),y=z(e=>{c.current&&c.current.updateConfig(e)},[]),b=z(()=>{if(c.current){const e=c.current.getPerformanceMode();return c.current.setPerformanceMode(!e),console.log("性能模式:",e?"已禁用":"已启用"),!e}return!1},[]),k=z(()=>c.current?.getStats()||{fps:0,renderTime:0,updateTime:0,totalRedPackets:0,activeRedPackets:0},[]),x=z(()=>c.current?.getCollectionStats()||{totalCollected:0,totalValue:0},[]),C=z(()=>{c.current&&c.current.resetCollectionStats()},[]),v=z(()=>c.current?.getPerformanceMode()||!1,[]),S=z(e=>{c.current&&c.current.setPerformanceMode(e)},[]);return $(()=>(h(),()=>{u()}),[]),{engineRef:c,start:f,stop:g,pause:m,resume:p,clear:P,updateConfig:y,togglePerformanceMode:b,getStats:k,getCollectionStats:x,resetCollectionStats:C,getPerformanceMode:v,setPerformanceMode:S}},{useRef:E,useMemo:D,useCallback:A}=t,L=t.forwardRef((e,i)=>{const{config:a={},className:n="",style:r={},autoStart:o=!0,showControls:s=!0,onRedPacketClick:c,onAnimationStateChange:d,onPerformanceUpdate:h}=e,u=t.useRef(null),{currentConfig:f,handleConfigChange:g,updateConfig:P,toggleDebugMode:b,toggleFrameLimit:x}=((e={})=>{const[t,i]=S({...F,...e}),a=R((e,t)=>{let a;return i(i=>(a={...i},"minSpeed"===e?a.speed={...a.speed,min:t}:"maxSpeed"===e?a.speed={...a.speed,max:t}:a[e]=t,a)),a},[]),n=R(e=>{let t;return i(i=>(t={...i,...e},t)),t},[]),r=R(()=>{let e,a;return i(t=>(e=!t.debugMode,a={...t,debugMode:e},console.log("调试模式:",e?"开启":"关闭"),a)),{newConfig:{...t,debugMode:!t.debugMode},debugMode:!t.debugMode}},[t]),o=R(()=>{let e,a;return i(t=>(e=!t.enableFrameRateLimit,a={...t,enableFrameRateLimit:e},console.log("帧率限制:",e?"已启用":"已关闭"),a)),{newConfig:{...t,enableFrameRateLimit:!t.enableFrameRateLimit},frameLimitEnabled:!t.enableFrameRateLimit}},[t]);return{currentConfig:t,setCurrentConfig:i,handleConfigChange:a,updateConfig:n,toggleDebugMode:r,toggleFrameLimit:o}})(a),{engineRef:j,start:T,stop:$,pause:z,resume:E,clear:L,updateConfig:W,togglePerformanceMode:O,getStats:_,getCollectionStats:N,resetCollectionStats:H,getPerformanceMode:V,setPerformanceMode:U}=I(u,f,o,c,d,h),{stats:B,startStatsUpdate:q}=(e=>{const[i,a]=t.useState({fps:0,collected:0,totalValue:0,activeCount:0,performanceMode:"性能模式"}),n=t.useRef(null),r=M(()=>{if(!e.current)return;const t=e.current.getStats(),i=e.current.getCollectionStats(),n=e.current.getPerformanceMode()?"性能模式":"高质量";a({fps:t.fps,collected:i.totalCollected,totalValue:i.totalValue,activeCount:t.activeRedPackets,performanceMode:`${n}(限制已启用)`})},[e]),o=M(()=>{n.current&&clearInterval(n.current),n.current=setInterval(()=>{r()},100)},[r]),s=M(()=>{n.current&&(clearInterval(n.current),n.current=null)},[]);return w(()=>()=>{s()},[s]),{stats:i,updateStats:r,startStatsUpdate:o,stopStatsUpdate:s}})(j);t.useEffect(()=>{q()},[q]);const X=D(()=>m,[]),J=D(()=>p(r),[r]),Y=A(()=>{const e=b();j.current&&j.current.updateConfig({debugMode:e.debugMode})},[b,j]),K=A(()=>O(),[O]),G=A(()=>{const e=x();j.current&&j.current.updateConfig({enableFrameRateLimit:e.frameLimitEnabled})},[x,j]),Q=A((e,t)=>{const i=g(e,t);i&&W(i)},[g,W]);return t.useImperativeHandle(i,()=>({start:T,stop:$,pause:z,resume:E,clear:L,updateConfig:e=>{P(e),W(e)},getStats:_,getCollectionStats:N,resetCollectionStats:H,getEngine:()=>j.current,togglePerformanceMode:O,setPerformanceMode:U,getPerformanceMode:V}),[T,$,z,E,L,P,W,_,N,H,j,O,U,V]),l.jsxs("div",{className:n,children:[s&&l.jsxs(l.Fragment,{children:[l.jsx(y,{stats:B}),l.jsx(k,{onStart:T,onStop:$,onPause:z,onResume:E,onClear:L,onToggleDebug:Y,onTogglePerformance:K,onToggleFrameLimit:G,isPerformanceMode:f.enablePerformanceMode,isDebugMode:f.debugMode,isFrameLimitEnabled:f.enableFrameRateLimit}),l.jsx(C,{config:f,onConfigChange:Q})]}),l.jsx("div",{style:J,children:l.jsx("canvas",{ref:u,style:X})}),s&&l.jsx(v,{})]})});L.displayName="RedPacketRain";e.RedPacketRain=L,e.RedPacketRainEngine=a,e.VERSION="1.0.0",e.default=L,Object.defineProperty(e,"__esModule",{value:!0})}); //# sourceMappingURL=index.umd.js.map