oho-spin
Version:
A customizable spinning wheel module with interactive features
3 lines (2 loc) • 9.36 kB
JavaScript
"use strict";let t=null;function e(e){t&&i(),t=new Audio(e),t.loop=!0,t.play().catch((t=>console.error("Audio playback failed:",t)))}function i(){t&&(t.pause(),t.currentTime=0,t=null)}function n(t,e){return Math.floor(Math.random()*(e-t+1))+t}module.exports=class{constructor(t){this.angle=0,this.isSpinning=!1,this.lastMouseX=null,this.lastMouseY=null,this.images={},this.overlayImg=null,this.rotationSpeed=1,this.targetQuadrant=null,this.winningResult=null,this.handleMouseDown=t=>{this.lastMouseX=t.clientX,this.lastMouseY=t.clientY},this.handleMouseMove=t=>{if(null===this.lastMouseX||null===this.lastMouseY)return;const e=t.clientX-this.lastMouseX,i=t.clientY-this.lastMouseY;this.angle+=.01*(e-i),this.drawWheel(),this.lastMouseX=t.clientX,this.lastMouseY=t.clientY},this.handleMouseUp=()=>{this.lastMouseX=null,this.lastMouseY=null},this.handleTouchStart=t=>{const e=t.touches[0];this.lastMouseX=e.clientX,this.lastMouseY=e.clientY},this.handleTouchMove=t=>{t.preventDefault();const e=t.touches[0];this.handleMouseMove({clientX:e.clientX,clientY:e.clientY})},this.config=Object.assign({spinDuration:4e3,soundEnabled:!0,pointerAngle:0,isInteractive:!0,easing:"easeOut",resultPosition:"top",is3D:!0},t);const e="string"==typeof this.config.container?document.querySelector(this.config.container):this.config.container;if(!(e&&e instanceof HTMLElement))throw new Error("Container not found");this.canvas=document.createElement("canvas"),this.canvas.width=440,this.canvas.height=440,e.appendChild(this.canvas),this.ctx=this.canvas.getContext("2d"),this.preloadImages(),this.config.isInteractive&&this.setupInteraction(),this.drawWheel()}preloadImages(){this.config.quadrants.forEach((t=>{if(t.image){const e=new Image;e.src=t.image,e.onload=()=>{this.images[t.image]=e,this.drawWheel()},e.onerror=()=>console.error(`Failed to preload image: ${t.image}`)}if(t.backgroundImage){const e=new Image;e.src=t.backgroundImage,e.onload=()=>{console.log(`Background image preloaded: ${t.backgroundImage}`),this.images[t.backgroundImage]=e,this.drawWheel()},e.onerror=()=>console.error(`Failed to preload background image: ${t.backgroundImage}`)}})),this.config.overlayImage&&(this.overlayImg=new Image,this.overlayImg.src=this.config.overlayImage,this.overlayImg.onload=()=>{this.drawWheel()},this.overlayImg.onerror=()=>console.error(`Failed to preload overlay image: ${this.config.overlayImage}`))}drawWheel(){const t=this.ctx,e=this.canvas.width/2,i=this.canvas.height/2,n=Math.min(e,i)-20;t.clearRect(0,0,this.canvas.width,this.canvas.height);let s=0;switch(this.config.resultPosition){case"right":default:s=0;break;case"left":s=Math.PI;break;case"bottom":s=Math.PI/2;break;case"top":s=3*Math.PI/2}const a=2*Math.PI/this.config.quadrants.length;if(this.config.quadrants.forEach(((o,h)=>{const r=this.angle+h*a+s,l=r+a;t.save(),t.beginPath(),t.moveTo(e,i),t.arc(e,i,n,r,l),t.closePath(),this.config.is3D&&(t.shadowColor="rgba(0, 0, 0, 0.5)",t.shadowBlur=10,t.shadowOffsetX=5,t.shadowOffsetY=5),o.backgroundImage&&this.images[o.backgroundImage]?(t.clip(),t.translate(e,i),t.rotate(r),t.drawImage(this.images[o.backgroundImage],-n,-n,2*n,2*n),t.rotate(-r),t.translate(-e,-i)):(t.fillStyle=o.color||"#ffffff",t.fill()),t.restore(),o.image&&this.images[o.image]&&(t.save(),t.translate(e,i),t.rotate(r+a/2),t.drawImage(this.images[o.image],n/2-20,-20,40,40),t.restore()),t.save(),t.translate(e,i),t.rotate(r+a/2),t.fillStyle=o.textColor||"#000",t.font=o.fontStyle||`${o.fontSize||16}px Arial`,t.textAlign="center";const c=n/2,g=1.2*(o.fontSize||16),u=o.text.split(" ");let d="",f=n-40;for(let e=0;e<u.length;e++){const i=d+u[e]+" ";t.measureText(i).width>c&&e>0?(t.save(),t.translate(f,0),t.rotate(Math.PI/2),t.fillText(d.trim(),0,0),t.restore(),d=u[e]+" ",f-=g):d=i}t.save(),t.translate(f,0),t.rotate(Math.PI/2),t.fillText(d.trim(),0,0),t.restore(),t.restore()})),this.winningResult||this.config.isInteractive){let s=0,a=0,o=0,h=0;const r=20,l=n+10,c=n+50;switch(this.config.resultPosition){case"top":s=e,a=i-l,o=e,h=i-c,this.config.isInteractive&&(t.beginPath(),t.moveTo(s,a-r/2),t.lineTo(s-r/2,a+r/2),t.lineTo(s+r/2,a+r/2),t.fillStyle="#ff0000",t.fill());break;case"bottom":s=e,a=i+l,o=e,h=i+c,this.config.isInteractive&&(t.beginPath(),t.moveTo(s,a+r/2),t.lineTo(s-r/2,a-r/2),t.lineTo(s+r/2,a-r/2),t.fillStyle="#ff0000",t.fill());break;case"left":s=e-l,a=i,o=e-c,h=i,this.config.isInteractive&&(t.beginPath(),t.moveTo(s-r/2,a),t.lineTo(s+r/2,a-r/2),t.lineTo(s+r/2,a+r/2),t.fillStyle="#ff0000",t.fill());break;case"right":s=e+l,a=i,o=e+c,h=i,this.config.isInteractive&&(t.beginPath(),t.moveTo(s+r/2,a),t.lineTo(s-r/2,a-r/2),t.lineTo(s-r/2,a+r/2),t.fillStyle="#ff0000",t.fill())}this.winningResult&&(t.font="20px Arial",t.fillStyle="#ffffff",t.textAlign="center",t.fillText(`You won: ${this.winningResult.text}`,o,h))}this.overlayImg&&t.drawImage(this.overlayImg,0,0,this.canvas.width,this.canvas.height)}spinToIndex(t,s){if(this.isSpinning)return;if(t<0||t>=this.config.quadrants.length)return void console.error(`Invalid index: ${t}. Must be between 0 and ${this.config.quadrants.length-1}`);if(s<=0)return void console.error("Speed must be positive");this.isSpinning=!0,this.targetQuadrant=this.config.quadrants[t],this.winningResult=null,this.rotationSpeed=s;const a=360/this.config.quadrants.length,o=(t*a+a/2)%360,h=360*n(5,10)+(360-o-this.config.pointerAngle),r=performance.now();this.config.soundEnabled&&e(this.config.soundFile);const l=t=>{var e,n;const s=t-r,a=Math.min(s/this.config.spinDuration,1);let o;switch(this.config.easing){case"linear":o=a;break;case"cubicOut":o=1-Math.pow(1-a,3);break;default:o=1-Math.pow(1-a,4)}this.angle=h*o*Math.PI/180,this.drawWheel(),a<1?requestAnimationFrame(l):(this.isSpinning=!1,this.winningResult=this.getWinningQuadrant(),this.config.soundEnabled&&i(),this.drawWheel(),null===(n=(e=this.config).onSpinComplete)||void 0===n||n.call(e,this.winningResult))};requestAnimationFrame(l)}spin(){if(this.isSpinning)return;this.isSpinning=!0,this.targetQuadrant=null,this.winningResult=null;const t=360*n(5,10)*this.rotationSpeed,s=performance.now();this.config.soundEnabled&&e(this.config.soundFile);const a=e=>{var n,o;const h=e-s,r=Math.min(h/this.config.spinDuration,1);let l;switch(this.config.easing){case"linear":l=r;break;case"cubicOut":l=1-Math.pow(1-r,3);break;default:l=1-Math.pow(1-r,4)}this.angle=t*l*Math.PI/180,this.drawWheel(),r<1?requestAnimationFrame(a):(this.isSpinning=!1,this.winningResult=this.getWinningQuadrant(),this.config.soundEnabled&&i(),this.drawWheel(),null===(o=(n=this.config).onSpinComplete)||void 0===o||o.call(n,this.winningResult))};requestAnimationFrame(a)}setWinningQuadrant(t){if(this.isSpinning)return;this.isSpinning=!0;const s=this.config.quadrants.find((e=>e.text===t));if(!s)return console.error(`Quadrant "${t}" not found`),void(this.isSpinning=!1);this.targetQuadrant=s,this.winningResult=null;const a=360/this.config.quadrants.length,o=(this.config.quadrants.indexOf(s)*a+a/2)%360,h=360*n(5,10)+(360-o-this.config.pointerAngle),r=performance.now();this.config.soundEnabled&&e(this.config.soundFile);const l=t=>{var e,n;const s=t-r,a=Math.min(s/this.config.spinDuration,1);let o;switch(this.config.easing){case"linear":o=a;break;case"cubicOut":o=1-Math.pow(1-a,3);break;default:o=1-Math.pow(1-a,4)}this.angle=h*o*Math.PI*this.rotationSpeed/180,this.drawWheel(),a<1?requestAnimationFrame(l):(this.isSpinning=!1,this.winningResult=this.getWinningQuadrant(),this.config.soundEnabled&&i(),this.drawWheel(),null===(n=(e=this.config).onSpinComplete)||void 0===n||n.call(e,this.winningResult))};requestAnimationFrame(l)}setRotationSpeed(t){t<=0?console.error("Speed must be positive"):this.rotationSpeed=t}reset(){this.angle=0,this.isSpinning=!1,this.rotationSpeed=1,this.targetQuadrant=null,this.winningResult=null,this.drawWheel()}getCurrentQuadrant(){return this.getWinningQuadrant()}stopSpin(){var t,e;this.isSpinning&&(this.isSpinning=!1,this.winningResult=this.getWinningQuadrant(),this.config.soundEnabled&&i(),this.drawWheel(),null===(e=(t=this.config).onSpinComplete)||void 0===e||e.call(t,this.winningResult))}toggleInteractivity(t){t&&!this.config.isInteractive?(this.setupInteraction(),this.config.isInteractive=!0):!t&&this.config.isInteractive&&(this.removeInteraction(),this.config.isInteractive=!1),this.drawWheel()}getWinningQuadrant(){const t=360/this.config.quadrants.length,e=(180*this.angle/Math.PI+this.config.pointerAngle)%360,i=Math.floor((360-e)/t)%this.config.quadrants.length;return this.config.quadrants[i]}setupInteraction(){this.canvas.addEventListener("mousedown",this.handleMouseDown),this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseup",this.handleMouseUp),this.canvas.addEventListener("touchstart",this.handleTouchStart),this.canvas.addEventListener("touchmove",this.handleTouchMove),this.canvas.addEventListener("touchend",this.handleMouseUp)}removeInteraction(){this.canvas.removeEventListener("mousedown",this.handleMouseDown),this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseup",this.handleMouseUp),this.canvas.removeEventListener("touchstart",this.handleTouchStart),this.canvas.removeEventListener("touchmove",this.handleTouchMove),this.canvas.removeEventListener("touchend",this.handleMouseUp)}};
//# sourceMappingURL=oho-spin.cjs.js.map