@ahmiao666/red-packet-rain-vue
Version:
3 lines (2 loc) • 26.8 kB
JavaScript
import{defineComponent as t,ref as e,reactive as i,computed as a,watchEffect as n,onMounted as s,onUnmounted as o,openBlock as l,createElementBlock as c,createCommentVNode as r,createElementVNode as d,toDisplayString as h,normalizeClass as f,withDirectives as g,vModelText as u,normalizeStyle as p,nextTick as m}from"vue";const P={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 v{constructor(t,e){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=t,this.ctx=t.getContext("2d"),this.config={...P,...e},this.optimizeConfig(),this.resizeCanvas(),this.initializePool(),this.initializeParticlePool(),this.bindEvents(),this.loadRedPacketImage()}initializePool(){for(let t=0;t<this.poolSize;t++)this.redPacketPool.push(this.createRedPacket())}initializeParticlePool(){for(let t=0;t<this.particlePoolSize;t++)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(t){this.particlePool.length<this.particlePoolSize&&this.particlePool.push(t)}resetParticle(t,e,i){const a=this.particleConfig,n=Math.random()*a.spread,s=a.speed.min+Math.random()*(a.speed.max-a.speed.min);t.x=e,t.y=i,t.vx=Math.cos(n)*s,t.vy=Math.sin(n)*s-2*Math.random(),t.size=a.size.min+Math.random()*(a.size.max-a.size.min),t.initialSize=void 0,t.opacity=1,t.color=a.colors[Math.floor(Math.random()*a.colors.length)],t.maxLife=a.life.min+Math.random()*(a.life.max-a.life.min),t.life=t.maxLife,t.gravity=a.gravity,t.friction=a.friction,t.rotation=Math.random()*Math.PI*2,t.rotationSpeed=.2*(Math.random()-.5)}getRedPacketFromPool(){const t=this.redPacketPool.pop()||this.createRedPacket();return this.resetRedPacket(t),t}returnRedPacketToPool(t){this.redPacketPool.length<this.poolSize&&this.redPacketPool.push(t)}getRedPacketData(){if(!this.config.redPackets||"number"==typeof this.config.redPackets)return null;if(Array.isArray(this.config.redPackets)&&this.config.redPackets.length>0){const t=this.config.redPackets[this.redPacketDataIndex];return this.redPacketDataIndex=(this.redPacketDataIndex+1)%this.config.redPackets.length,t}return null}isSpecialRedPacket(t){return!!this.config.isSpecialFn&&("function"==typeof this.config.isSpecialFn?this.config.isSpecialFn(t):"string"==typeof this.config.isSpecialFn&&!!t[this.config.isSpecialFn])}createRedPacket(){const t=this.getRedPacketData(),e={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 t&&this.isUsingArrayMode()?(e.id=t.id||e.id,e.value=t.value||e.value,e.type=this.isSpecialRedPacket(t)?"special":"normal",e.originalData=t):(e.type="normal",e.originalData=null),e}resetRedPacket(t){const e=this.getRedPacketData();t.x=Math.random()*(this.actualWidth-this.config.size.width),t.y=-this.config.size.height,t.speed=Number(this.config.speed.min)+Math.random()*(Number(this.config.speed.max)-Number(this.config.speed.min)),t.rotation=0,t.rotationSpeed=this.config.rotation?this.config.rotationSpeed.min+Math.random()*(this.config.rotationSpeed.max-this.config.rotationSpeed.min):0,t.scale=.8+.4*Math.random(),t.opacity=1,t.collected=!1,e&&this.isUsingArrayMode()?(t.id=e.id||t.id,t.value=e.value||Math.floor(100*Math.random())+1,t.type=this.isSpecialRedPacket(e)?"special":"normal",t.originalData=e):(t.value=Math.floor(100*Math.random())+1,t.type="normal",t.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 t=800,e=600;if("string"==typeof this.config.containerWidth&&this.config.containerWidth.includes("%")){const e=this.canvas.parentElement;e&&(t=e.clientWidth*parseFloat(this.config.containerWidth)/100)}else t="number"==typeof this.config.containerWidth?this.config.containerWidth:800;if("string"==typeof this.config.containerHeight&&this.config.containerHeight.includes("%")){const t=this.canvas.parentElement;t&&(e=t.clientHeight*parseFloat(this.config.containerHeight)/100)}else e="number"==typeof this.config.containerHeight?this.config.containerHeight:600;this.canvas.width=this.actualWidth=Math.max(100,Math.min(t,4e3)),this.canvas.height=this.actualHeight=Math.max(100,Math.min(e,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(t){const e=this.getCanvasCoordinates(t.clientX,t.clientY);this.checkCollision(e.x,e.y,"mouse")}handleTouch(t){t.preventDefault();const e=t.touches[0],i=this.getCanvasCoordinates(e.clientX,e.clientY);this.checkCollision(i.x,i.y,"touch")}getCanvasCoordinates(t,e){const i=this.canvas.getBoundingClientRect(),a=i.width,n=i.height,s=this.canvas.width/a,o=this.canvas.height/n,l=(t-i.left)*s,c=(e-i.top)*o;return this.config.debugMode&&console.log(`🎯 点击坐标转换:\n 客户端坐标: (${t}, ${e})\n Canvas矩形: ${JSON.stringify(i)}\n 缩放比例: (${s.toFixed(3)}, ${o.toFixed(3)})\n 最终坐标: (${l.toFixed(1)}, ${c.toFixed(1)})`),{x:l,y:c}}handleResize(){this.resizeCanvas()}checkCollision(t,e,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(`🎯 检查碰撞: (${t.toFixed(1)}, ${e.toFixed(1)}) [${i}]`);let n=!1;for(let i=this.redPackets.length-1;i>=0;i--){const a=this.redPackets[i];if(this.isPointInRedPacket(t,e,a)){this.config.debugMode&&console.log(`🎯 命中红包: ${a.id}, 类型: ${a.type}, 价值: ${a.value}`),this.collectRedPacket(a,t,e),this.redPackets.splice(i,1),this.returnRedPacketToPool(a),n=!0;break}}this.config.debugMode&&(this.debugClicks.push({x:t,y:e,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,s=i.y+i.height/2,o=Math.sqrt((t-n)**2+(e-s)**2);console.log(`红包${a+1}: 中心(${n.toFixed(1)}, ${s.toFixed(1)}), 距离: ${o.toFixed(1)}`)})))}isPointInRedPacket(t,e,i){const a=i.x+i.width/2,n=i.y+i.height/2,s=i.width*i.scale,o=i.height*i.scale,l=s+.1*s,c=o+.1*o,r=t>=a-l/2&&t<=a+l/2&&e>=n-c/2&&e<=n+c/2;return this.config.debugMode&&r&&console.log(`🎯 红包边界检测:\n 红包中心: (${a.toFixed(1)}, ${n.toFixed(1)})\n 原始尺寸: ${s.toFixed(1)} x ${o.toFixed(1)}\n 扩展尺寸: ${l.toFixed(1)} x ${c.toFixed(1)}\n 点击坐标: (${t.toFixed(1)}, ${e.toFixed(1)})\n 距离中心: (${Math.abs(t-a).toFixed(1)}, ${Math.abs(e-n).toFixed(1)})`),r}collectRedPacket(t,e,i){t.collected=!0,this.stats.totalCollected++,this.stats.totalValue+=t.value,!this.config.enablePerformanceMode&&this.config.isParticle&&this.createRedPacketParticles(t,e,i),this.onRedPacketClickCallback&&this.onRedPacketClickCallback({redPacket:t,x:e,y:i,value:t.value})}createRedPacketParticles(t,e,i){const a=this.particleConfig.count,n="special"===t.type?1.5*a:a;for(let a=0;a<n;a++){const a=this.getParticleFromPool();this.resetParticle(a,e,i),"special"===t.type&&(a.color="#FFD700",a.size*=1.3),this.particles.push(a)}this.config.debugMode&&console.log(`🎆 创建了 ${n} 个粒子 [红包类型: ${t.type}]`)}updateParticles(t){const e=t/16.67;for(let i=this.particles.length-1;i>=0;i--){const a=this.particles[i];a.x+=a.vx*e,a.y+=a.vy*e,a.vy+=a.gravity*e,a.vx*=a.friction,a.vy*=a.friction,a.rotation+=a.rotationSpeed*e,a.life-=t;const n=Math.max(0,a.life/a.maxLife);a.opacity=n,a.initialSize||(a.initialSize=a.size);const s=.3+.7*n;a.size=a.initialSize*s,(a.life<=0||a.y>this.actualHeight+50)&&(this.particles.splice(i,1),this.returnParticleToPool(a))}}renderParticles(){const t=this.ctx;for(const e of this.particles){t.save(),t.globalAlpha=e.opacity,t.translate(e.x,e.y),t.rotate(e.rotation);const i=t.createRadialGradient(0,0,0,0,0,e.size);i.addColorStop(0,e.color),i.addColorStop(.7,e.color+"80"),i.addColorStop(1,e.color+"00"),t.fillStyle=i,t.beginPath(),t.arc(0,0,e.size,0,2*Math.PI),t.fill(),"#FFD700"===e.color&&!this.config.enablePerformanceMode&&(t.shadowColor=e.color,t.shadowBlur=2*e.size,t.beginPath(),t.arc(0,0,.5*e.size,0,2*Math.PI),t.fill()),t.restore()}}spawnRedPacket(){const t=Date.now(),e=1e3/this.config.density;if(t-this.lastSpawnTime>e&&this.redPackets.length<this.config.count){const e=this.getRedPacketFromPool();this.redPackets.push(e),this.lastSpawnTime=t}}updateRedPackets(t){for(let e=this.redPackets.length-1;e>=0;e--){const i=this.redPackets[e];i.y+=i.speed*(t/16.67),this.config.rotation&&(i.rotation+=i.rotationSpeed*(t/16.67)),i.y>this.actualHeight&&(this.redPackets.splice(e,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 t of this.redPackets)this.renderRedPacket(t)}renderRedPacket(t){const e=this.ctx,i=t.x+t.width/2,a=t.y+t.height/2;e.save(),e.globalAlpha=t.opacity,e.translate(i,a),this.config.rotation&&e.rotate(t.rotation),e.scale(t.scale,t.scale),!this.config.enablePerformanceMode&&"special"===t.type&&(e.shadowColor="#FFD700",e.shadowBlur=10),this.redPacketImage?e.drawImage(this.redPacketImage,-t.width/2,-t.height/2,t.width,t.height):this.drawDefaultRedPacket(e,t),e.restore()}drawDefaultRedPacket(t,e){const i=e.width,a=e.height;t.fillStyle="special"===e.type?"#FFD700":"#FF6B6B",t.fillRect(-i/2,-a/2,i,a),t.strokeStyle=this.config.customStyles?.borderColor||"#FF4444",t.lineWidth=2,t.strokeRect(-i/2,-a/2,i,a),t.fillStyle="#FFFFFF",t.font="20px Arial",t.textAlign="center",t.textBaseline="middle",t.fillText("¥",0,-5),e.value&&(t.font="10px Arial",t.fillText(e.value.toString(),0,8))}animate(t){if(!this.isRunning||this.isPaused)return;const e=1e3/(this.config.enablePerformanceMode?this.config.maxFPS:this.config.qualityMaxFPS||144),i=t-this.lastFrameTime;i<.9*e||(this.lastFrameTime=t,this.updateFPS(t),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(t){this.frameCount++,t-this.lastFpsTime>=1e3&&(this.stats.fps=this.frameCount,this.frameCount=0,this.lastFpsTime=t)}renderDebugInfo(){const t=this.ctx;t.save(),t.fillStyle="rgba(0, 0, 0, 0.8)",t.fillRect(10,10,300,120),t.fillStyle="#00FF00",t.font="14px Arial",t.textAlign="left",t.fillText(`FPS: ${this.stats.fps}`,15,30),t.fillText(`红包数量: ${this.redPackets.length}`,15,50),t.fillText(`粒子数量: ${this.particles.length}`,15,70),t.fillText(`Canvas尺寸: ${this.actualWidth}x${this.actualHeight}`,15,90),t.fillText(`点击记录: ${this.debugClicks.length}`,15,110);for(const e of this.redPackets){const i=e.x+e.width/2,a=e.y+e.height/2,n=e.width*e.scale,s=e.height*e.scale,o=n+.1*n,l=s+.1*s;t.strokeStyle="rgba(255, 0, 0, 0.5)",t.lineWidth=1,t.strokeRect(i-n/2,a-s/2,n,s),t.strokeStyle="rgba(0, 255, 0, 0.7)",t.lineWidth=2,t.strokeRect(i-o/2,a-l/2,o,l),t.fillStyle="rgba(0, 255, 255, 0.8)",t.fillRect(i-2,a-2,4,4)}const e=Date.now();for(const i of this.debugClicks){const a=e-i.time;if(a<2e3){const e=Math.max(0,1-a/2e3);t.fillStyle=i.hit?`rgba(0, 255, 0, ${e})`:`rgba(255, 0, 0, ${e})`,t.fillRect(i.x-5,i.y-5,10,10),t.strokeStyle=i.hit?`rgba(0, 255, 0, ${e})`:`rgba(255, 0, 0, ${e})`,t.lineWidth=2,t.beginPath(),t.arc(i.x,i.y,15,0,2*Math.PI),t.stroke()}}t.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(t=>this.returnRedPacketToPool(t)),this.redPackets=[],this.particles.forEach(t=>this.returnParticleToPool(t)),this.particles=[],this.ctx.clearRect(0,0,this.actualWidth,this.actualHeight),this.stats.totalCollected=0,this.stats.totalValue=0}updateConfig(t){this.config={...this.config,...t},this.optimizeConfig(),this.resizeCanvas(),t.redPacketImage&&this.loadRedPacketImage(),t.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(t){this.config.enablePerformanceMode=t}getPerformanceMode(){return this.config.enablePerformanceMode}onRedPacketClick(t){this.onRedPacketClickCallback=t}onAnimationStateChange(t){this.onAnimationStateChangeCallback=t}onPerformanceUpdate(t){this.onPerformanceUpdateCallback=t}setParticleConfig(t){this.particleConfig={...this.particleConfig,...t}}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))}}const k={class:"red-packet-rain-container",style:{fontFamily:"Arial, sans-serif"}},b={key:0,class:"stats-panel"},x={class:"stats-grid"},y={class:"stats-item"},C={class:"stats-value"},F={class:"stats-item"},S={class:"stats-value"},M={class:"stats-item"},R={class:"stats-value"},w={class:"stats-item"},z={class:"stats-value"},T={class:"stats-item"},$={class:"stats-value"},I={key:1,class:"control-buttons"},D={key:2,class:"config-panel"},A={class:"config-item"},E={class:"config-value"},H={class:"config-item"},W={class:"config-value"},V={class:"config-item"},L={class:"config-value"},U={class:"config-item"},q={class:"config-value"},B={class:"config-item"},N={class:"config-value"},_=["width","height"],O={key:3,class:"instructions"};var j=t({__name:"VueRedPacketRain",props:{config:{type:Object,required:!1,default:()=>({})},className:{type:String,required:!1,default:""},style:{type:Object,required:!1,default:()=>({})},autoStart:{type:Boolean,required:!1,default:!0},showControls:{type:Boolean,required:!1,default:!0}},emits:["redPacketClick","animationStateChange","performanceUpdate"],setup(t,{expose:P,emit:j}){const Y=t,X=j,G=e(null),J=e(null),K=e(!1),Q=i({fps:0,collected:0,totalValue:0,activeCount:0,performanceMode:"性能模式"}),Z=i({count:15,density:3,speed:{min:2,max:5},maxFPS:60,qualityMaxFPS:144,enablePerformanceMode:!0,enableFrameRateLimit:!0,debugMode:!1,containerWidth:"100%",containerHeight:"100%",...Y.config}),tt=a(()=>({display:"block",width:"100%",height:"100%",...Y.style}));n(()=>{if(!J.value)return;const t=J.value.getStats(),e=Z.enablePerformanceMode?"性能模式":"高质量",i=Z.enableFrameRateLimit?"限制已启用":"无限制";Q.fps=t.fps,Q.collected=J.value.getCollectionStats().totalCollected,Q.totalValue=J.value.getCollectionStats().totalValue,Q.activeCount=t.activeRedPackets,Q.performanceMode=`${e}(${i})`});const et=async()=>{if(!G.value||J.value)return;await m();const t=G.value.getBoundingClientRect(),e={containerWidth:t.width||800,containerHeight:t.height||600,...Z};J.value=new v(G.value,e),J.value.onRedPacketClick(t=>{X("redPacketClick",t)}),J.value.onAnimationStateChange(t=>{X("animationStateChange",t)}),J.value.onPerformanceUpdate(t=>{X("performanceUpdate",t)}),K.value=!0,setTimeout(()=>{console.log("🎮 Vue红包雨组件已初始化"),console.log("🖥️ 正在检测显示器刷新率..."),(()=>{let t=0;const e=performance.now(),i=a=>{if(t++,a-e>=1e3){const e=t;console.log(`🖥️ 检测到显示器刷新率: ${e}Hz`),e<=60?console.log("📺 您的显示器: 60Hz"):e<=120?console.log("📺 您的显示器: 120Hz - 这解释了为什么看到120FPS而不是144FPS"):console.log("📺 您的显示器: 高刷新率,支持144FPS+")}else requestAnimationFrame(i)};requestAnimationFrame(i)})()},1e3),Y.autoStart&&J.value.start()},it=()=>{J.value&&J.value.updateConfig(Z)},at=()=>{J.value?.start()},nt=()=>{J.value?.stop()},st=()=>{J.value?.pause()},ot=()=>{J.value?.resume()},lt=()=>{J.value?.clear()},ct=()=>{Z.debugMode=!Z.debugMode,it(),console.log("调试模式:",Z.debugMode?"开启":"关闭")},rt=()=>{if(J.value){const t=J.value.getPerformanceMode();J.value.setPerformanceMode(!t),Z.enablePerformanceMode=!t,console.log("性能模式:",t?"已禁用":"已启用")}},dt=()=>{Z.enableFrameRateLimit=!Z.enableFrameRateLimit,it(),console.log("帧率限制:",Z.enableFrameRateLimit?"已启用":"已关闭")};return s(()=>{et()}),o(()=>{J.value&&(J.value.destroy(),J.value=null)}),P({start:at,stop:nt,pause:st,resume:ot,clear:lt,updateConfig:t=>{Object.assign(Z,t),it()},getStats:()=>J.value?.getStats()||{fps:0,renderTime:0,updateTime:0,totalRedPackets:0,activeRedPackets:0},getEngine:()=>J.value,togglePerformanceMode:()=>{if(J.value){const t=J.value.getPerformanceMode();return J.value.setPerformanceMode(!t),Z.enablePerformanceMode=!t,!t}return!1},setPerformanceMode:t=>{J.value?.setPerformanceMode(t),Z.enablePerformanceMode=t},getPerformanceMode:()=>J.value?.getPerformanceMode()||!1}),(t,e)=>(l(),c("div",k,[r(" 统计面板 "),t.showControls?(l(),c("div",b,[d("div",x,[d("div",y,[d("div",C,h(Q.fps),1),e[5]||(e[5]=d("div",{class:"stats-label"},"FPS",-1))]),d("div",F,[d("div",S,h(Q.collected),1),e[6]||(e[6]=d("div",{class:"stats-label"},"已收集",-1))]),d("div",M,[d("div",R,"¥"+h(Q.totalValue),1),e[7]||(e[7]=d("div",{class:"stats-label"},"总价值",-1))]),d("div",w,[d("div",z,h(Q.activeCount),1),e[8]||(e[8]=d("div",{class:"stats-label"},"活跃红包",-1))]),d("div",T,[d("div",$,h(Q.performanceMode),1),e[9]||(e[9]=d("div",{class:"stats-label"},"当前模式",-1))])])])):r("v-if",!0),r(" 控制按钮 "),t.showControls?(l(),c("div",I,[d("button",{class:"btn btn-primary",onClick:at},"🚀 开始"),d("button",{class:"btn btn-secondary",onClick:nt},"⏹️ 停止"),d("button",{class:"btn btn-secondary",onClick:st},"⏸️ 暂停"),d("button",{class:"btn btn-secondary",onClick:ot},"▶️ 继续"),d("button",{class:"btn btn-secondary",onClick:lt},"🧹 清空"),d("button",{class:f(["btn",Z.debugMode?"btn-primary":"btn-secondary"]),onClick:ct}," 🐛 "+h(Z.debugMode?"关闭调试":"调试模式"),3),d("button",{class:f(["btn",Z.enablePerformanceMode?"btn-primary":"btn-secondary"]),onClick:rt}," ⚡ "+h(Z.enablePerformanceMode?"高质量模式":"性能模式"),3),d("button",{class:f(["btn",Z.enableFrameRateLimit?"btn-primary":"btn-secondary"]),onClick:dt}," 🎯 "+h(Z.enableFrameRateLimit?"关闭限制":"启用限制"),3)])):r("v-if",!0),r(" 配置面板 "),t.showControls?(l(),c("div",D,[e[15]||(e[15]=d("h3",null,"⚙️ 配置调整",-1)),d("div",A,[e[10]||(e[10]=d("label",null,"红包数量",-1)),g(d("input",{type:"range",min:"5",max:"50","onUpdate:modelValue":e[0]||(e[0]=t=>Z.count=t),onInput:it},null,544),[[u,Z.count]]),d("span",E,h(Z.count),1)]),d("div",H,[e[11]||(e[11]=d("label",null,"红包密度",-1)),g(d("input",{type:"range",min:"1",max:"10","onUpdate:modelValue":e[1]||(e[1]=t=>Z.density=t),onInput:it},null,544),[[u,Z.density]]),d("span",W,h(Z.density),1)]),d("div",V,[e[12]||(e[12]=d("label",null,"最小速度",-1)),g(d("input",{type:"range",min:"1",max:"5","onUpdate:modelValue":e[2]||(e[2]=t=>Z.speed.min=t),onInput:it},null,544),[[u,Z.speed.min]]),d("span",L,h(Z.speed.min),1)]),d("div",U,[e[13]||(e[13]=d("label",null,"最大速度",-1)),g(d("input",{type:"range",min:"3",max:"10","onUpdate:modelValue":e[3]||(e[3]=t=>Z.speed.max=t),onInput:it},null,544),[[u,Z.speed.max]]),d("span",q,h(Z.speed.max),1)]),d("div",B,[e[14]||(e[14]=d("label",null,"高质量帧率",-1)),g(d("input",{type:"range",min:"60",max:"240","onUpdate:modelValue":e[4]||(e[4]=t=>Z.qualityMaxFPS=t),onInput:it},null,544),[[u,Z.qualityMaxFPS]]),d("span",N,h(Z.qualityMaxFPS),1)])])):r("v-if",!0),r(" Canvas容器 "),d("div",{class:f(["canvas-container",t.className])},[d("canvas",{ref_key:"canvasRef",ref:G,style:p(tt.value),width:Z.containerWidth,height:Z.containerHeight},null,12,_)],2),r(" 使用说明 "),t.showControls?(l(),c("div",O,e[16]||(e[16]=[d("h3",null,"📖 使用说明",-1),d("ul",null,[d("li",null,"🎯 点击红包进行收集,每个红包都有随机的价值"),d("li",null,"⚡ 金色红包为特殊红包,价值更高"),d("li",null,"🎛️ 使用滑块实时调整红包参数"),d("li",null,"📊 观察FPS和性能统计"),d("li",null,"🔍 性能模式:简化渲染、60FPS限制、对象池复用"),d("li",null,"🎨 高质量模式:完整视觉效果、144FPS限制、对象池复用"),d("li",null,"🖥️ 帧率受显示器刷新率限制,会自动检测并调整")],-1)]))):r("v-if",!0)]))}});!function(t,e){void 0===e&&(e={});var i=e.insertAt;if(t&&!(typeof document>"u")){var a=document.head||document.getElementsByTagName("head")[0],n=document.createElement("style");n.type="text/css","top"===i&&a.firstChild?a.insertBefore(n,a.firstChild):a.appendChild(n),n.styleSheet?n.styleSheet.cssText=t:n.appendChild(document.createTextNode(t))}}('\n.red-packet-rain-container[data-v-f127135f] {\n font-family: Arial, sans-serif;\n}\n.stats-panel[data-v-f127135f] {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 20px;\n margin-bottom: 20px;\n}\n.stats-grid[data-v-f127135f] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n}\n.stats-item[data-v-f127135f] {\n text-align: center;\n padding: 15px;\n background: white;\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.stats-value[data-v-f127135f] {\n font-size: 2em;\n font-weight: bold;\n color: #ff6b6b;\n}\n.stats-label[data-v-f127135f] {\n color: #666;\n margin-top: 5px;\n}\n.control-buttons[data-v-f127135f] {\n margin-bottom: 20px;\n display: flex;\n gap: 10px;\n flex-wrap: wrap;\n}\n.btn[data-v-f127135f] {\n padding: 12px 24px;\n border: none;\n border-radius: 25px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);\n margin: 5px;\n}\n.btn-primary[data-v-f127135f] {\n background: linear-gradient(45deg, #ff6b6b, #ffa500);\n color: white;\n}\n.btn-secondary[data-v-f127135f] {\n background: #6c757d;\n color: white;\n}\n.btn[data-v-f127135f]:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);\n}\n.config-panel[data-v-f127135f] {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 20px;\n margin-bottom: 20px;\n}\n.config-panel h3[data-v-f127135f] {\n margin: 0 0 20px 0;\n color: #ff6b6b;\n}\n.config-item[data-v-f127135f] {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 15px;\n}\n.config-item label[data-v-f127135f] {\n min-width: 80px;\n font-weight: 600;\n color: #333;\n}\n.config-item input[type="range"][data-v-f127135f] {\n flex: 1;\n height: 6px;\n background: #ddd;\n border-radius: 3px;\n outline: none;\n -webkit-appearance: none;\n appearance: none;\n}\n.config-item input[type="range"][data-v-f127135f]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 20px;\n height: 20px;\n background: #ff6b6b;\n border-radius: 50%;\n cursor: pointer;\n}\n.config-item input[type="range"][data-v-f127135f]::-moz-range-thumb {\n width: 20px;\n height: 20px;\n background: #ff6b6b;\n border-radius: 50%;\n cursor: pointer;\n border: none;\n}\n.config-value[data-v-f127135f] {\n min-width: 30px;\n text-align: center;\n font-weight: bold;\n color: #ff6b6b;\n}\n.canvas-container[data-v-f127135f] {\n width: 100%;\n height: 500px;\n overflow: hidden;\n}\n.instructions[data-v-f127135f] {\n background: linear-gradient(135deg, #e8f4f8 0%, #d4e6f1 100%);\n border-radius: 8px;\n padding: 25px;\n margin-top: 20px;\n}\n.instructions h3[data-v-f127135f] {\n color: #2c3e50;\n margin-top: 0;\n}\n.instructions ul[data-v-f127135f] {\n padding-left: 20px;\n}\n.instructions li[data-v-f127135f] {\n margin-bottom: 8px;\n color: #34495e;\n}\ncanvas[data-v-f127135f] {\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n}\n\n');var Y=((t,e)=>{const i=t.__vccOpts||t;for(const[t,a]of e)i[t]=a;return i})(j,[["__scopeId","data-v-f127135f"]]);const X="1.0.0";export{Y as RedPacketRain,v as RedPacketRainEngine,X as VERSION,Y as default};
//# sourceMappingURL=index.esm.js.map