UNPKG

wheel-fortune

Version:

A lightweight, customizable spinning wheel component for web games and raffles

3 lines (2 loc) 4.83 kB
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var o=class{rootElement=null;wheelElement=null;triggerElement=null;swayAnimation=null;swayingElement=null;finalRotation=new WeakMap;rotationCount;duration;overshootDeg;returnDuration;swayAmplitude;swayPeriod;rootClassName;spinStates;currentSpinIndex=0;hasSpun=!1;warmedUp=!1;onClick=()=>{this.runSpin()};constructor(t){this.options=t,this.rotationCount=t.rotationCount??6,this.duration=t.duration??5e3,this.overshootDeg=t.overshootDeg??15,this.returnDuration=t.returnDuration??1350,this.swayAmplitude=t.swayOptions?.amplitude??6,this.swayPeriod=t.swayOptions?.period??1500,this.spinStates=[...t.spinStates??[]];const e=t.rootSelector.trim();this.rootClassName=e.startsWith(".")?e.slice(1):e}init(){const t=document.querySelector(this.options.rootSelector),e=t?.querySelector(this.options.wheelSelector),i=t?.querySelector(this.options.triggerSelector);!t||!e||!i||(this.triggerElement&&this.triggerElement.removeEventListener("click",this.onClick),this.rootElement=t,this.wheelElement=e,this.triggerElement=i,this.warmUp(),this.triggerElement.addEventListener("click",this.onClick),this.startSway(this.wheelElement))}destroy(){this.stopSway(),this.wheelElement&&this.cancelAnimations(this.wheelElement),this.triggerElement&&this.triggerElement.removeEventListener("click",this.onClick),this.finalRotation=new WeakMap}reset(){if(!this.rootElement||!this.wheelElement||!this.triggerElement){this.init();return}this.destroy(),this.wheelElement.style.transform="",this.rootElement.classList.remove(`${this.rootClassName}--spinning`,`${this.rootClassName}--completed`,`${this.rootClassName}--first-done`,`${this.rootClassName}--final-done`),this.currentSpinIndex=0,this.hasSpun=!1,this.warmedUp=!1,this.warmUp(),this.triggerElement.addEventListener("click",this.onClick),this.startSway(this.wheelElement)}warmUp(){if(this.warmedUp||!this.wheelElement)return;const t=this.wheelElement.animate([{filter:"blur(0)"},{filter:"blur(0.4px)",offset:.5},{filter:"blur(0)"}],{duration:64,fill:"forwards"});this.wheelElement.getBoundingClientRect(),t.onfinish=()=>{t.commitStyles?.(),t.cancel()},this.decodeImages(this.wheelElement),this.warmedUp=!0}decodeImages(t){t.querySelectorAll("img").forEach(e=>{e.decode?.().catch(()=>{})})}async runSpin(){if(!this.rootElement||!this.wheelElement)return;const t=this.spinStates[this.currentSpinIndex];t&&(this.hasSpun=!0,this.rootElement.classList.remove(`${this.rootClassName}--completed`),this.rootElement.classList.add(`${this.rootClassName}--spinning`),this.stopSway(),await this.rotateWheelTo(this.wheelElement,t.targetAngle),this.rootElement.classList.remove(`${this.rootClassName}--spinning`),this.rootElement.classList.add(`${this.rootClassName}--completed`),this.currentSpinIndex===0&&this.rootElement.classList.add(`${this.rootClassName}--first-done`),this.currentSpinIndex===this.spinStates.length-1&&this.rootElement.classList.add(`${this.rootClassName}--final-done`),t.callback?.(),this.currentSpinIndex++)}async rotateWheelTo(t,e){const i=this.getCurrentRotation(t),s=(this.normalize(e)-this.normalize(i)+360)%360,n=i+this.rotationCount*360+s,a=n+this.overshootDeg,r=this.duration+this.returnDuration,l=this.duration/r,h=t.animate([{transform:`rotate(${i}deg)`,easing:"cubic-bezier(0.86,0,0.07,1)"},{offset:l,transform:`rotate(${a}deg)`,easing:"cubic-bezier(0.77,0,0.175,1)"},{transform:`rotate(${n}deg)`}],{duration:r,fill:"forwards"}),m=t.animate([{filter:"blur(0)"},{offset:.1,filter:"blur(0.4px)"},{offset:.25,filter:"blur(1px)"},{offset:.6,filter:"blur(1px)"},{offset:.9,filter:"blur(0.4px)"},{offset:1,filter:"blur(0)"}],{duration:r,fill:"forwards",easing:"ease-in-out"});await Promise.all([h.finished,m.finished]),this.finalRotation.set(t,this.normalize(n))}startSway(t){if(this.hasSpun)return;this.stopSway(),this.swayingElement=t;const e=this.finalRotation.get(t)??this.getCurrentRotation(t),i=this.normalize(e);this.swayAnimation=t.animate([{transform:`rotate(${i-this.swayAmplitude}deg)`},{transform:`rotate(${i+this.swayAmplitude}deg)`}],{duration:this.swayPeriod,direction:"alternate",iterations:Number.POSITIVE_INFINITY,easing:"ease-in-out",delay:-this.swayPeriod/2})}stopSway(){if(!this.swayAnimation||!this.swayingElement)return;const t=this.swayingElement,e=getComputedStyle(t).transform;this.swayAnimation.commitStyles?.(),this.swayAnimation.cancel(),t.style.transform=e!=="none"?e:"",this.swayAnimation=null,this.swayingElement=null}normalize(t){return(t%360+360)%360}getCurrentRotation(t){const e=getComputedStyle(t).transform;if(!e||e==="none")return 0;const{a:i,b:s}=new DOMMatrixReadOnly(e);return Math.atan2(s,i)*180/Math.PI}cancelAnimations(t){t.getAnimations().forEach(e=>{e.cancel()})}};exports.WheelFortune=o;exports.default=o; //# sourceMappingURL=index.cjs.js.map