diff --git a/dist/spin-wheel-esm.js b/dist/spin-wheel-esm.js index 62c1ae8..2ecde28 100644 --- a/dist/spin-wheel-esm.js +++ b/dist/spin-wheel-esm.js @@ -1,7 +1,7 @@ /** - * Spin Wheel (ESM) v2.1.0 + * Spin Wheel (ESM) v2.2.0 * https://github.com/CrazyTim/spin-wheel#readme * Copyright (c) CrazyTim 2022. * Distributed under the MIT License. */ -var b=Math.pow;function R(n=0,t=0){return n=Math.ceil(n),t=Math.floor(t),Math.floor(Math.random()*(t-n))+n}function g(n=0){return n*Math.PI/180}function _(n,t){let e=0;for(let i of n){let o=i[t];o&&(e+=typeof o=="number"?o:1)}return e}function x(n,t,e){return t0?i=e%360:i=360+e%360,i===360&&(i=0),i}function M(n=0,t=0){let e=180-t,i=L(n,e);return 180-i}var c=-90,f=500,p=250,A=Object.freeze({left:"left",right:"right",center:"center"}),s=Object.freeze({borderColor:"#000",borderWidth:0,debug:!1,image:null,isInteractive:!0,itemBackgroundColor:"#fff",itemBackgroundColors:[],itemImage:null,itemImageSize:1,itemImageRadius:.5,itemLabel:"",itemLabelAlign:A.right,itemLabelBaselineOffset:0,itemLabelColor:"#000",itemLabelColors:[],itemLabelFont:"sans-serif",itemLabelFontSizeMax:f,itemLabelRadius:.85,itemLabelRadiusMax:.2,itemLabelRotation:0,itemWeight:1,items:[],lineColor:"#000",lineWidth:1,radius:.95,rotation:0,rotationResistance:-35,rotationSpeed:0,rotationSpeedMax:250,offset:{w:0,h:0},onCurrentIndexChange:null,onRest:null,onSpin:null,overlayImage:null,pointerRotation:0}),v=Object.freeze({pointerLineColor:"#ff00ff",labelOutlineColor:"#ff00ff",dragEventHue:200});function z(n={}){let t=n.canvas;"PointerEvent"in window?(t.addEventListener("pointerdown",o),t.addEventListener("pointermove",e)):(t.addEventListener("touchstart",u),t.addEventListener("mousedown",r),t.addEventListener("mousemove",i));function e(a={}){let l={x:a.clientX,y:a.clientY};n.isCursorOverWheel=n.wheelHitTest(l),n.refreshCursor()}function i(a={}){let l={x:a.clientX,y:a.clientY};n.isCursorOverWheel=n.wheelHitTest(l),n.refreshCursor()}function o(a={}){let l={x:a.clientX,y:a.clientY};if(!n.isInteractive||!n.wheelHitTest(l))return;a.preventDefault(),n.dragStart(l),t.setPointerCapture(a.pointerId),t.addEventListener("pointermove",m),t.addEventListener("pointerup",h),t.addEventListener("pointercancel",h);function m(d={}){d.preventDefault(),n.dragMove({x:d.clientX,y:d.clientY})}function h(d={}){d.preventDefault(),t.releasePointerCapture(d.pointerId),t.removeEventListener("pointermove",m),t.removeEventListener("pointerup",h),t.removeEventListener("pointercancel",h),n.dragEnd()}}function r(a={}){let l={x:a.clientX,y:a.clientY};if(!n.isInteractive||!n.wheelHitTest(l))return;n.dragStart(l),document.addEventListener("mousemove",m),document.addEventListener("mouseup",h);function m(d={}){d.preventDefault(),n.dragMove({x:d.clientX,y:d.clientY})}function h(d={}){d.preventDefault(),document.removeEventListener("mousemove",m),document.removeEventListener("mouseup",h),n.dragEnd()}}function u(a={}){let l={x:a.targetTouches[0].clientX,y:a.targetTouches[0].clientY};if(!n.isInteractive||!n.wheelHitTest(l))return;a.preventDefault(),n.dragStart(l),t.addEventListener("touchmove",m),t.addEventListener("touchend",h),t.addEventListener("touchcancel",h);function m(d={}){d.preventDefault(),n.dragMove({x:d.targetTouches[0].clientX,y:d.targetTouches[0].clientY})}function h(d={}){d.preventDefault(),t.removeEventListener("touchmove",m),t.removeEventListener("touchend",h),t.removeEventListener("touchcancel",h),n.dragEnd()}}}var w=class{constructor(t,e={}){this.canvasContainer=t,this.initCanvas(),this._borderColor=s.borderColor,this._borderWidth=s.borderWidth,this._debug=s.debug,this._image=s.image,this._isInteractive=s.isInteractive,this._itemBackgroundColors=s.itemBackgroundColors,this._itemLabelAlign=s.itemLabelAlign,this._itemLabelBaselineOffset=s.itemLabelBaselineOffset,this._itemLabelColors=s.itemLabelColors,this._itemLabelFont=s.itemLabelFont,this._itemLabelFontSizeMax=s.itemLabelFontSizeMax,this._itemLabelRadius=s.itemLabelRadius,this._itemLabelRadiusMax=s.itemLabelRadiusMax,this._itemLabelRotation=s.itemLabelRotation,this._items=s.items,this._lineColor=s.lineColor,this._lineWidth=s.lineWidth,this._rotationSpeedMax=s.rotationSpeedMax,this._radius=s.radius,this._rotation=s.rotation,this._rotationResistance=s.rotationResistance,this._rotationSpeed=s.rotationSpeed,this._offset=s.offset,this._onCurrentIndexChange=s.onCurrentIndexChange,this._onRest=s.onRest,this._onSpin=s.onSpin,this._overlayImage=s.overlayImage,this._pointerRotation=s.pointerRotation,e&&this.init(e)}initCanvas(){for(;this.canvasContainer.firstChild;)this.canvasContainer.removeChild(this.canvasContainer.firstChild);this.canvas=document.createElement("canvas"),this.canvasContainer.appendChild(this.canvas),this.context=this.canvas.getContext("2d"),this.registerEvents()}init(t={}){this.borderColor=t.borderColor,this.borderWidth=t.borderWidth,this.debug=t.debug,this.image=t.image,this.isInteractive=t.isInteractive,this.itemBackgroundColors=t.itemBackgroundColors,this.itemLabelAlign=t.itemLabelAlign,this.itemLabelBaselineOffset=t.itemLabelBaselineOffset,this.itemLabelColors=t.itemLabelColors,this.itemLabelFont=t.itemLabelFont,this.itemLabelFontSizeMax=t.itemLabelFontSizeMax,this.itemLabelRadius=t.itemLabelRadius,this.itemLabelRadiusMax=t.itemLabelRadiusMax,this.itemLabelRotation=t.itemLabelRotation,this.items=t.items,this.lineColor=t.lineColor,this.lineWidth=t.lineWidth,this.rotationSpeedMax=t.rotationSpeedMax,this.radius=t.radius,this.rotation=t.rotation,this.rotationResistance=t.rotationResistance,this.rotationSpeed=t.rotationSpeed,this.offset=t.offset,this.onCurrentIndexChange=t.onCurrentIndexChange,this.onRest=t.onRest,this.onSpin=t.onSpin,this.overlayImage=t.overlayImage,this.pointerRotation=t.pointerRotation,this.resize()}registerEvents(){window.addEventListener("resize",()=>this.resize()),z(this)}resize(){window.cancelAnimationFrame(this.frameRequestId);let[t,e]=[this.canvasContainer.clientWidth,this.canvasContainer.clientHeight],i=Math.min(t,e),o={w:i-i*this.offset.w,h:i-i*this.offset.h},r=Math.min(t/o.w,e/o.h);this.size=Math.max(o.w*r,o.h*r),this.canvas.style.width=t+"px",this.canvas.style.height=e+"px",this.canvas.width=t,this.canvas.height=e,this.center={x:t/2+t*this.offset.w,y:e/2+e*this.offset.h},this.actualRadius=this.size/2*this.radius,this.itemLabelFontSize=this.itemLabelFontSizeMax*(this.size/f),this.labelMaxWidth=this.actualRadius*(this.itemLabelRadius-this.itemLabelRadiusMax);for(let u of this.actualItems)this.itemLabelFontSize=Math.min(this.itemLabelFontSize,y(u.label,this.itemLabelFont,this.labelMaxWidth,this.context));this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}draw(t=0){let e=this.context;e.clearRect(0,0,this.canvas.width,this.canvas.height),this.lastFrame===void 0&&(this.lastFrame=t);let i=(t-this.lastFrame)/1e3;i>0&&(this.rotation+=i*this.rotationSpeed,this.rotation=this.rotation%360),this.lastFrame=t;let o=this.getItemAngles(this.rotation),r=this.borderWidth/f*this.size;for(let[a,l]of o.entries())e.beginPath(),e.moveTo(this.center.x,this.center.y),e.arc(this.center.x,this.center.y,this.actualRadius-r/2,g(l.start+c),g(l.end+c)),e.closePath(),e.fillStyle=this.actualItems[a].backgroundColor,e.fill();this.refreshCurrentIndex(o),this.drawItemLines(e,o),this.drawBorder(e),e.textBaseline="middle",e.textAlign=this.itemLabelAlign,e.font=this.itemLabelFontSize+"px "+this.itemLabelFont;let u=this.itemLabelFontSize*-this.itemLabelBaselineOffset;e.save();for(let[a,l]of o.entries()){let m=this.actualItems[a];if(!m.label)continue;e.save();let h=l.start+(l.end-l.start)/2;e.translate(this.center.x+Math.cos(g(h+c))*(this.actualRadius*this.itemLabelRadius),this.center.y+Math.sin(g(h+c))*(this.actualRadius*this.itemLabelRadius)),e.rotate(g(h+c)),this.debug&&(e.beginPath(),e.moveTo(0,0),e.lineTo(-this.labelMaxWidth,0),e.strokeStyle=v.labelOutlineColor,e.lineWidth=1,e.stroke(),e.strokeRect(0,-this.itemLabelFontSize/2,-this.labelMaxWidth,this.itemLabelFontSize)),e.rotate(g(this.itemLabelRotation)),e.fillStyle=m.labelColor,e.fillText(m.label,0,u),e.restore()}this.drawItemImages(e,o),this.drawImage(e,this.image,!1),this.drawImage(e,this.overlayImage,!0),this.drawPointerLine(e),this.drawDragEvents(e),this.applyDrag(i),this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}drawItemImages(t,e=[]){for(let[i,o]of e.entries()){let r=this.actualItems[i];if(!r.image||!r.image.complete||r.image.error)continue;t.save();let u=o.start+(o.end-o.start)/2;t.translate(this.center.x+Math.cos(g(u+c))*(this.actualRadius*r.imageRadius),this.center.y+Math.sin(g(u+c))*(this.actualRadius*r.imageRadius)),t.rotate(g(u));let a=this.size/500*r.image.width*r.imageSize,l=this.size/500*r.image.height*r.imageSize,m=-a/2,h=-l/2;t.drawImage(r.image,m,h,a,l),t.restore()}}drawImage(t,e,i=!1){if(!e)return;t.save(),t.translate(this.center.x,this.center.y),i||t.rotate(g(this.rotation));let o=i?this.size:this.size*this.radius,r=-(o/2);t.drawImage(e,r,r,o,o),t.restore()}drawPointerLine(t,e,i=!1){!this.debug||(t.save(),t.translate(this.center.x,this.center.y),t.rotate(g(this.pointerRotation+c)),t.beginPath(),t.moveTo(0,0),t.lineTo(this.actualRadius*2,0),t.strokeStyle=v.pointerLineColor,t.lineWidth=2,t.stroke(),t.restore())}drawBorder(t){let e=this.borderWidth/f*this.size;t.beginPath(),t.strokeStyle=this.borderColor,t.lineWidth=e,t.arc(this.center.x,this.center.y,this.actualRadius-e/2,0,2*Math.PI),t.stroke()}drawItemLines(t,e=[]){if(this.lineWidth<=0)return;let i=this.lineWidth/f*this.size;t.save(),t.translate(this.center.x,this.center.y);for(let[o,r]of e.entries())t.rotate(g(r.start+c)),t.beginPath(),t.moveTo(0,0),t.lineTo(this.actualRadius-i,0),t.strokeStyle=this.lineColor,t.lineWidth=i,t.stroke(),t.rotate(-g(r.start+c));t.restore()}drawDragEvents(){var e;if(!this.debug||!((e=this.dragEvents)==null?void 0:e.length))return;let t=[...this.dragEvents].reverse();for(let[i,o]of t.entries()){let r=i/this.dragEvents.length*100;ctx.beginPath(),ctx.arc(o.x,o.y,5,0,2*Math.PI),ctx.fillStyle=`hsl(${v.dragEventHue},100%,${r}%)`,ctx.strokeStyle="#000",ctx.lineWidth=.5,ctx.fill(),ctx.stroke()}}applyDrag(t=0){var i;if(this.rotationSpeed===0)return;let e=this.rotationSpeed+this.rotationResistance*t*this.rotationDirection;(this.rotationDirection===1&&e<0||this.rotationDirection===-1&&e>=0)&&(e=0),this.rotationSpeed=e,this.rotationSpeed===0&&((i=this.onRest)==null||i.call(this,{event:"rest",currentIndex:this._currentIndex}))}spin(t=0,e=0){var o;let i=e/2;this.rotationSpeed=R(t*(1-i),t*(1+i)),this.rotationSpeed!==0&&((o=this.onSpin)==null||o.call(this,{event:"spin",direction:this.rotationDirection,rotationSpeed:this.rotationSpeed}))}getRotationDirection(t=0){return t>0?1:-1}wheelHitTest(t={x:0,y:0}){let e=C(t,this.canvas);return I(e,this.center.x,this.center.y,this.actualRadius)}refreshCursor(){if(this.isDragging){this.canvas.style.cursor="grabbing";return}if(this.isInteractive&&this.isCursorOverWheel){this.canvas.style.cursor="grab";return}this.canvas.style.cursor=null}processItems(){this.actualItems=[];for(let[t,e]of this.items.entries()){let i={};typeof e.backgroundColor=="string"?i.backgroundColor=e.backgroundColor:this.itemBackgroundColors.length?i.backgroundColor=this.itemBackgroundColors[t%this.itemBackgroundColors.length]:i.backgroundColor=s.itemBackgroundColor,typeof e.label=="string"?i.label=e.label:i.label=s.itemLabel,typeof e.labelFont=="string"?i.labelFont=e.labelFont:i.labelFont=this.itemLabelFont,typeof e.labelColor=="string"?i.labelColor=e.labelColor:this.itemLabelColors.length?i.labelColor=this.itemLabelColors[t%this.itemLabelColors.length]:i.labelColor=s.itemLabelColor,typeof e.weight=="number"?i.weight=e.weight:i.weight=s.itemWeight,typeof e.image=="string"?(i.image=new Image,i.image.src=e.image,i.image.onerror=o=>(i.image.error=!0,!0)):i.image=s.itemImage,typeof e.imageSize=="number"?i.imageSize=e.imageSize:i.imageSize=s.itemImageSize,typeof e.imageRadius=="number"?i.imageRadius=e.imageRadius:i.imageRadius=s.itemImageRadius,this.actualItems.push(i)}this.actualItems.length?this.weightedItemAngle=360/_(this.actualItems,"weight"):this.weightedItemAngle=0}getAngleFromCenter(t={x:0,y:0}){return(S(this.center.x,this.center.y,t.x,t.y)+90)%360}getCurrentIndex(){return this._currentIndex}refreshCurrentIndex(t=[]){var e;for(let[i,o]of t.entries())if(!!x(this.pointerRotation,o.start%360,o.end%360)){if(this._currentIndex===i)break;this._currentIndex=i,(e=this.onCurrentIndexChange)==null||e.call(this,{event:"CurrentIndexChange",currentIndex:this._currentIndex})}}getItemAngles(t=0){let e=[],i,o=t;for(let r of this.actualItems)i=r.weight*this.weightedItemAngle,e.push({start:o,end:o+i}),o+=i;return e}get borderColor(){return this._borderColor}set borderColor(t){typeof t=="string"?this._borderColor=t:this._borderColor=s.borderColor}get borderWidth(){return this._borderWidth}set borderWidth(t){typeof t=="number"?this._borderWidth=t:this._borderWidth=s.borderWidth}get debug(){return this._debug}set debug(t){typeof t=="boolean"?this._debug=t:this._debug=s.debug}get image(){return this._image}set image(t){typeof t=="string"?(this._image=new Image,this._image.src=t):this._image=s.image}get isInteractive(){return this._isInteractive}set isInteractive(t){typeof t=="boolean"?this._isInteractive=t:this._isInteractive=s.isInteractive}get itemBackgroundColors(){return this._itemBackgroundColors}set itemBackgroundColors(t){Array.isArray(t)?this._itemBackgroundColors=t:this._itemBackgroundColors=s.itemBackgroundColors,this.processItems()}get itemLabelAlign(){return this._itemLabelAlign}set itemLabelAlign(t){typeof t=="string"?this._itemLabelAlign=t:this._itemLabelAlign=s.itemLabelAlign}get itemLabelBaselineOffset(){return this._itemLabelBaselineOffset}set itemLabelBaselineOffset(t){typeof t=="number"?this._itemLabelBaselineOffset=t:this._itemLabelBaselineOffset=s.itemLabelBaselineOffset,this.resize()}get itemLabelColors(){return this._itemLabelColors}set itemLabelColors(t){Array.isArray(t)?this._itemLabelColors=t:this._itemLabelColors=s.itemLabelColors,this.processItems()}get itemLabelFont(){return this._itemLabelFont}set itemLabelFont(t){typeof t=="string"?this._itemLabelFont=t:this._itemLabelFont=s.itemLabelFont,this.resize()}get itemLabelFontSizeMax(){return this._itemLabelFontSizeMax}set itemLabelFontSizeMax(t){typeof t=="number"?this._itemLabelFontSizeMax=t:this._itemLabelFontSizeMax=s.itemLabelFontSizeMax}get itemLabelRadius(){return this._itemLabelRadius}set itemLabelRadius(t){typeof t=="number"?this._itemLabelRadius=t:this._itemLabelRadius=s.itemLabelRadius}get itemLabelRadiusMax(){return this._itemLabelRadiusMax}set itemLabelRadiusMax(t){typeof t=="number"?this._itemLabelRadiusMax=t:this._itemLabelRadiusMax=s.itemLabelRadiusMax}get itemLabelRotation(){return this._itemLabelRotation}set itemLabelRotation(t){typeof t=="number"?this._itemLabelRotation=t:this._itemLabelRotation=s.itemLabelRotation}get items(){return this._items}set items(t){Array.isArray(t)?this._items=t:this._items=s.items,this.processItems()}get lineColor(){return this._lineColor}set lineColor(t){typeof t=="string"?this._lineColor=t:this._lineColor=s.lineColor}get lineWidth(){return this._lineWidth}set lineWidth(t){typeof t=="number"?this._lineWidth=t:this._lineWidth=s.lineWidth}get radius(){return this._radius}set radius(t){typeof t=="number"?this._radius=t:this._radius=s.radius,this.resize()}get rotation(){return this._rotation}set rotation(t){typeof t=="number"?this._rotation=t:this._rotation=s.rotation}get rotationResistance(){return this._rotationResistance}set rotationResistance(t){typeof t=="number"?this._rotationResistance=t:this._rotationResistance=s.rotationResistance}get rotationSpeed(){return this._rotationSpeed}set rotationSpeed(t){if(typeof t=="number"){let e=Math.min(t,this.rotationSpeedMax);e=Math.max(e,-this.rotationSpeedMax),this.rotationDirection=this.getRotationDirection(e),this._rotationSpeed=e}else this.rotationDirection=0,this._rotationSpeed=s.rotationSpeed}get rotationSpeedMax(){return this._rotationSpeedMax}set rotationSpeedMax(t){typeof t=="number"?this._rotationSpeedMax=t:this._rotationSpeedMax=s.rotationSpeedMax}get offset(){return this._offset}set offset(t){t?this._offset=t:this._offset=s.offset,this.resize()}get onCurrentIndexChange(){return this._onCurrentIndexChange}set onCurrentIndexChange(t){typeof t=="function"?this._onCurrentIndexChange=t:this._onCurrentIndexChange=s.onCurrentIndexChange}get onRest(){return this._onRest}set onRest(t){typeof t=="function"?this._onRest=t:this._onRest=s.onRest}get onSpin(){return this._onSpin}set onSpin(t){typeof t=="function"?this._onSpin=t:this._onSpin=s.onSpin}get overlayImage(){return this._overlayImage}set overlayImage(t){typeof t=="string"?(this._overlayImage=new Image,this._overlayImage.src=t):this._overlayImage=s.overlayImage}get pointerRotation(){return this._pointerRotation}set pointerRotation(t){typeof t=="number"?this._pointerRotation=t:this._pointerRotation=s.pointerRotation}dragStart(t={x:0,y:0}){let e=C(t,this.canvas),i=-this.getAngleFromCenter(e);this.isDragging=!0,this.rotationSpeed=0,this.dragStartRotation=L(i,this.rotation),this.dragEvents=[{distance:0,x:e.x,y:e.y,now:performance.now()}],this.refreshCursor()}dragMove(t={x:0,y:0}){let e=C(t,this.canvas),i=this.getAngleFromCenter(e),o=this.dragEvents[0],r=this.getAngleFromCenter(o),u=M(r,i);this.dragEvents.unshift({distance:u,x:e.x,y:e.y,now:performance.now()}),this.debug&&this.dragEvents.length>=40&&this.dragEvents.pop(),this.rotation=L(i,this.dragStartRotation)}dragEnd(){var i;this.isDragging=!1,clearInterval(this.dragClearOldDistances);let t=0,e=performance.now();for(let[o,r]of this.dragEvents.entries()){if(!this.isDragEventTooOld(e,r)){t+=r.distance;continue}this.dragEvents.length=o;break}t!==0&&(this.rotationSpeed=t*(1e3/p),(i=this.onSpin)==null||i.call(this,{event:"spin",rotationDirection:this.rotationDirection,rotationSpeed:this.rotationSpeed,dragEvents:[...this.dragEvents]})),this.refreshCursor()}isDragEventTooOld(t,e={}){return t-e.now>p}};export{w as Wheel}; +var f=Math.pow;function L(n=0,e=0){return n=Math.ceil(n),e=Math.floor(e),Math.floor(Math.random()*(e-n))+n}function l(n=0){return n*Math.PI/180}function p(n,e){let t=0;for(let i of n){let s=i[e];s&&(t+=typeof s=="number"?s:1)}return t}function R(n,e,t){return e0?i=t%360:i=360+t%360,i===360&&(i=0),i}function S(n=0,e=0){let t=180-e,i=v(n,t);return 180-i}function w(n){return typeof n=="object"&&!Array.isArray(n)&&n!==null}var h=-90,m=500,_=250,z=Object.freeze({left:"left",right:"right",center:"center"}),o=Object.freeze({wheel:{borderColor:"#000",borderWidth:0,debug:!1,image:null,isInteractive:!0,itemBackgroundColors:[],itemLabelAlign:z.right,itemLabelBaselineOffset:0,itemLabelColors:[],itemLabelFont:"sans-serif",itemLabelFontSizeMax:m,itemLabelRadius:.85,itemLabelRadiusMax:.2,itemLabelRotation:0,items:[],lineColor:"#000",lineWidth:1,radius:.95,rotation:0,rotationResistance:-35,rotationSpeed:0,rotationSpeedMax:250,offset:{w:0,h:0},onCurrentIndexChange:null,onRest:null,onSpin:null,overlayImage:null,pointerRotation:0},item:{backgroundColor:"#fff",image:null,imageRadius:.5,imageSize:1,label:"",labelColor:"#000",weight:1}}),C=Object.freeze({pointerLineColor:"#ff00ff",labelOutlineColor:"#ff00ff",dragEventHue:200});function M(n={}){let e=n.canvas;n._handler_onPointerMoveRefreshCursor=(t={})=>{let i={x:t.clientX,y:t.clientY};n.isCursorOverWheel=n.wheelHitTest(i),n.refreshCursor()},n._handler_onMouseMoveRefreshCursor=(t={})=>{let i={x:t.clientX,y:t.clientY};n.isCursorOverWheel=n.wheelHitTest(i),n.refreshCursor()},n._handler_onPointerDown=(t={})=>{let i={x:t.clientX,y:t.clientY};if(!n.isInteractive||!n.wheelHitTest(i))return;t.preventDefault(),n.dragStart(i),e.setPointerCapture(t.pointerId),e.addEventListener("pointermove",s),e.addEventListener("pointerup",r),e.addEventListener("pointercancel",r);function s(a={}){a.preventDefault(),n.dragMove({x:a.clientX,y:a.clientY})}function r(a={}){a.preventDefault(),e.releasePointerCapture(a.pointerId),e.removeEventListener("pointermove",s),e.removeEventListener("pointerup",r),e.removeEventListener("pointercancel",r),n.dragEnd()}},n._handler_onMouseDown=(t={})=>{let i={x:t.clientX,y:t.clientY};if(!n.isInteractive||!n.wheelHitTest(i))return;n.dragStart(i),document.addEventListener("mousemove",s),document.addEventListener("mouseup",r);function s(a={}){a.preventDefault(),n.dragMove({x:a.clientX,y:a.clientY})}function r(a={}){a.preventDefault(),document.removeEventListener("mousemove",s),document.removeEventListener("mouseup",r),n.dragEnd()}},n._handler_onTouchStart=(t={})=>{let i={x:t.targetTouches[0].clientX,y:t.targetTouches[0].clientY};if(!n.isInteractive||!n.wheelHitTest(i))return;t.preventDefault(),n.dragStart(i),e.addEventListener("touchmove",s),e.addEventListener("touchend",r),e.addEventListener("touchcancel",r);function s(a={}){a.preventDefault(),n.dragMove({x:a.targetTouches[0].clientX,y:a.targetTouches[0].clientY})}function r(a={}){a.preventDefault(),e.removeEventListener("touchmove",s),e.removeEventListener("touchend",r),e.removeEventListener("touchcancel",r),n.dragEnd()}},"PointerEvent"in window?(e.addEventListener("pointerdown",n._handler_onPointerDown),e.addEventListener("pointermove",n._handler_onPointerMoveRefreshCursor)):(e.addEventListener("touchstart",n._handler_onTouchStart),e.addEventListener("mousedown",n._handler_onMouseDown),e.addEventListener("mousemove",n._handler_onMouseMoveRefreshCursor)),n._handler_onResize=n.resize.bind(n),window.addEventListener("resize",n._handler_onResize)}function A(n={}){let e=n.canvas;"PointerEvent"in window?(e.removeEventListener("pointerdown",n._handler_onPointerDown),e.removeEventListener("pointermove",n._handler_onPointerMoveRefreshCursor)):(e.removeEventListener("touchstart",n._handler_onTouchStart),e.removeEventListener("mousedown",n._handler_onMouseDown),e.removeEventListener("mousemove",n._handler_onMouseMoveRefreshCursor)),window.removeEventListener("resize",n._handler_onResize)}var E=class{constructor(e,t={}){if(!(e instanceof Element))throw"container parameter must be an Element";if(!w(t))throw"props parameter must be an Object";this.canvasContainer=e,this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.addCanvas(),M(this);for(let i of Object.keys(o.wheel))this["_"+i]=o.wheel[i];t&&this.init(o.wheel)}init(e={}){this._isInitialising=!0,this.borderColor=e.borderColor,this.borderWidth=e.borderWidth,this.debug=e.debug,this.image=e.image,this.isInteractive=e.isInteractive,this.itemBackgroundColors=e.itemBackgroundColors,this.itemLabelAlign=e.itemLabelAlign,this.itemLabelBaselineOffset=e.itemLabelBaselineOffset,this.itemLabelColors=e.itemLabelColors,this.itemLabelFont=e.itemLabelFont,this.itemLabelFontSizeMax=e.itemLabelFontSizeMax,this.itemLabelRadius=e.itemLabelRadius,this.itemLabelRadiusMax=e.itemLabelRadiusMax,this.itemLabelRotation=e.itemLabelRotation,this.items=e.items,this.lineColor=e.lineColor,this.lineWidth=e.lineWidth,this.rotationSpeedMax=e.rotationSpeedMax,this.radius=e.radius,this.rotation=e.rotation,this.rotationResistance=e.rotationResistance,this.rotationSpeed=e.rotationSpeed,this.offset=e.offset,this.onCurrentIndexChange=e.onCurrentIndexChange,this.onRest=e.onRest,this.onSpin=e.onSpin,this.overlayImage=e.overlayImage,this.pointerRotation=e.pointerRotation}addCanvas(){this.canvasContainer.appendChild(this.canvas)}removeCanvas(){this.canvasContainer.removeChild(this.canvas)}remove(){window.cancelAnimationFrame(this.frameRequestId),A(this),this.removeCanvas()}resize(){window.cancelAnimationFrame(this.frameRequestId);let[e,t]=[this.canvasContainer.clientWidth,this.canvasContainer.clientHeight],i=Math.min(e,t),s={w:i-i*this.offset.w,h:i-i*this.offset.h},r=Math.min(e/s.w,t/s.h);this.size=Math.max(s.w*r,s.h*r),this.canvas.style.width=e+"px",this.canvas.style.height=t+"px",this.canvas.width=e,this.canvas.height=t,this.center={x:e/2+e*this.offset.w,y:t/2+t*this.offset.h},this.actualRadius=this.size/2*this.radius,this.itemLabelFontSize=this.itemLabelFontSizeMax*(this.size/m),this.labelMaxWidth=this.actualRadius*(this.itemLabelRadius-this.itemLabelRadiusMax);for(let a of this.actualItems)this.itemLabelFontSize=Math.min(this.itemLabelFontSize,y(a.label,this.itemLabelFont,this.labelMaxWidth,this.context));this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}draw(e=0){let t=this.context;t.clearRect(0,0,this.canvas.width,this.canvas.height),this.lastFrame===void 0&&(this.lastFrame=e);let i=(e-this.lastFrame)/1e3;i>0&&(this.rotation+=i*this.rotationSpeed,this.rotation=this.rotation%360),this.lastFrame=e;let s=this.getItemAngles(this.rotation),r=this.borderWidth/m*this.size;for(let[u,d]of s.entries())t.beginPath(),t.moveTo(this.center.x,this.center.y),t.arc(this.center.x,this.center.y,this.actualRadius-r/2,l(d.start+h),l(d.end+h)),t.closePath(),t.fillStyle=this.actualItems[u].backgroundColor,t.fill();this.drawItemLines(t,s),this.drawBorder(t),t.textBaseline="middle",t.textAlign=this.itemLabelAlign,t.font=this.itemLabelFontSize+"px "+this.itemLabelFont;let a=this.itemLabelFontSize*-this.itemLabelBaselineOffset;t.save();for(let[u,d]of s.entries()){let g=this.actualItems[u];if(!g.label)continue;t.save();let c=d.start+(d.end-d.start)/2;t.translate(this.center.x+Math.cos(l(c+h))*(this.actualRadius*this.itemLabelRadius),this.center.y+Math.sin(l(c+h))*(this.actualRadius*this.itemLabelRadius)),t.rotate(l(c+h)),this.debug&&(t.beginPath(),t.moveTo(0,0),t.lineTo(-this.labelMaxWidth,0),t.strokeStyle=C.labelOutlineColor,t.lineWidth=1,t.stroke(),t.strokeRect(0,-this.itemLabelFontSize/2,-this.labelMaxWidth,this.itemLabelFontSize)),t.rotate(l(this.itemLabelRotation)),t.fillStyle=g.labelColor,t.fillText(g.label,0,a),t.restore()}this.drawItemImages(t,s),this.drawImage(t,this.image,!1),this.drawImage(t,this.overlayImage,!0),this.drawPointerLine(t),this.drawDragEvents(t),this.applyDrag(i),this._isInitialising=!1,this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}drawItemImages(e,t=[]){for(let[i,s]of t.entries()){let r=this.actualItems[i];if(!r.image||!r.image.complete||r.image.error)continue;e.save();let a=s.start+(s.end-s.start)/2;e.translate(this.center.x+Math.cos(l(a+h))*(this.actualRadius*r.imageRadius),this.center.y+Math.sin(l(a+h))*(this.actualRadius*r.imageRadius)),e.rotate(l(a));let u=this.size/500*r.image.width*r.imageSize,d=this.size/500*r.image.height*r.imageSize,g=-u/2,c=-d/2;e.drawImage(r.image,g,c,u,d),e.restore()}}drawImage(e,t,i=!1){if(!t)return;e.save(),e.translate(this.center.x,this.center.y),i||e.rotate(l(this.rotation));let s=i?this.size:this.size*this.radius,r=-(s/2);e.drawImage(t,r,r,s,s),e.restore()}drawPointerLine(e,t,i=!1){!this.debug||(e.save(),e.translate(this.center.x,this.center.y),e.rotate(l(this.pointerRotation+h)),e.beginPath(),e.moveTo(0,0),e.lineTo(this.actualRadius*2,0),e.strokeStyle=C.pointerLineColor,e.lineWidth=2,e.stroke(),e.restore())}drawBorder(e){let t=this.borderWidth/m*this.size;e.beginPath(),e.strokeStyle=this.borderColor,e.lineWidth=t,e.arc(this.center.x,this.center.y,this.actualRadius-t/2,0,2*Math.PI),e.stroke()}drawItemLines(e,t=[]){if(this.lineWidth<=0)return;let i=this.lineWidth/m*this.size;e.save(),e.translate(this.center.x,this.center.y);for(let[s,r]of t.entries())e.rotate(l(r.start+h)),e.beginPath(),e.moveTo(0,0),e.lineTo(this.actualRadius-i,0),e.strokeStyle=this.lineColor,e.lineWidth=i,e.stroke(),e.rotate(-l(r.start+h));e.restore()}drawDragEvents(){var t;if(!this.debug||!((t=this.dragEvents)==null?void 0:t.length))return;let e=[...this.dragEvents].reverse();for(let[i,s]of e.entries()){let r=i/this.dragEvents.length*100;ctx.beginPath(),ctx.arc(s.x,s.y,5,0,2*Math.PI),ctx.fillStyle=`hsl(${C.dragEventHue},100%,${r}%)`,ctx.strokeStyle="#000",ctx.lineWidth=.5,ctx.fill(),ctx.stroke()}}applyDrag(e=0){var i;if(this.rotationSpeed===0)return;let t=this.rotationSpeed+this.rotationResistance*e*this.rotationDirection;(this.rotationDirection===1&&t<0||this.rotationDirection===-1&&t>=0)&&(t=0),this.rotationSpeed=t,this.rotationSpeed===0&&((i=this.onRest)==null||i.call(this,{event:"rest",currentIndex:this._currentIndex}))}spin(e=0,t=0){var s;let i=t/2;this.rotationSpeed=L(e*(1-i),e*(1+i)),this.dragEvents=[],this.rotationSpeed!==0&&((s=this.onSpin)==null||s.call(this,{event:"spin",direction:this.rotationDirection,rotationSpeed:this.rotationSpeed,dragEvents:[...this.dragEvents]}))}getRotationDirection(e=0){return e>0?1:-1}wheelHitTest(e={x:0,y:0}){let t=b(e,this.canvas);return x(t,this.center.x,this.center.y,this.actualRadius)}refreshCursor(){if(this.isDragging){this.canvas.style.cursor="grabbing";return}if(this.isInteractive&&this.isCursorOverWheel){this.canvas.style.cursor="grab";return}this.canvas.style.cursor=null}processItems(){this.actualItems=[];for(let[e,t]of this.items.entries()){let i={};typeof t.backgroundColor=="string"?i.backgroundColor=t.backgroundColor:this.itemBackgroundColors.length?i.backgroundColor=this.itemBackgroundColors[e%this.itemBackgroundColors.length]:i.backgroundColor=o.item.backgroundColor,typeof t.label=="string"?i.label=t.label:i.label=o.item.label,typeof t.labelFont=="string"?i.labelFont=t.labelFont:i.labelFont=this.itemLabelFont,typeof t.labelColor=="string"?i.labelColor=t.labelColor:this.itemLabelColors.length?i.labelColor=this.itemLabelColors[e%this.itemLabelColors.length]:i.labelColor=o.item.labelColor,typeof t.weight=="number"?i.weight=t.weight:i.weight=o.item.weight,typeof t.image=="string"?(i.image=new Image,i.image.src=t.image,i.image.onerror=s=>(i.image.error=!0,!0)):i.image=o.item.image,typeof t.imageSize=="number"?i.imageSize=t.imageSize:i.imageSize=o.item.imageSize,typeof t.imageRadius=="number"?i.imageRadius=t.imageRadius:i.imageRadius=o.item.imageRadius,this.actualItems.push(i)}this.actualItems.length?this.weightedItemAngle=360/p(this.actualItems,"weight"):this.weightedItemAngle=0}getAngleFromCenter(e={x:0,y:0}){return(I(this.center.x,this.center.y,e.x,e.y)+90)%360}getCurrentIndex(){return this._currentIndex}refreshCurrentIndex(e=[]){var t;this.actualItems.length===0&&(this._currentIndex=-1);for(let[i,s]of e.entries())if(!!R(this.pointerRotation,s.start%360,s.end%360)){if(this._currentIndex===i)break;this._currentIndex=i,this._isInitialising||(t=this.onCurrentIndexChange)==null||t.call(this,{event:"currentIndexChange",currentIndex:this._currentIndex});break}}getItemAngles(e=0){let t=[],i,s=e;for(let r of this.actualItems)i=r.weight*this.weightedItemAngle,t.push({start:s,end:s+i}),s+=i;return this.actualItems.length>1&&(t[t.length-1].end=t[0].start+360),t}get borderColor(){return this._borderColor}set borderColor(e){typeof e=="string"?this._borderColor=e:this._borderColor=o.wheel.borderColor}get borderWidth(){return this._borderWidth}set borderWidth(e){typeof e=="number"?this._borderWidth=e:this._borderWidth=o.wheel.borderWidth}get debug(){return this._debug}set debug(e){typeof e=="boolean"?this._debug=e:this._debug=o.wheel.debug}get image(){return this._image}set image(e){typeof e=="string"?(this._image=new Image,this._image.src=e):this._image=o.wheel.image}get isInteractive(){return this._isInteractive}set isInteractive(e){typeof e=="boolean"?this._isInteractive=e:this._isInteractive=o.wheel.isInteractive}get itemBackgroundColors(){return this._itemBackgroundColors}set itemBackgroundColors(e){Array.isArray(e)?this._itemBackgroundColors=e:this._itemBackgroundColors=o.wheel.itemBackgroundColors,this.processItems()}get itemLabelAlign(){return this._itemLabelAlign}set itemLabelAlign(e){typeof e=="string"?this._itemLabelAlign=e:this._itemLabelAlign=o.wheel.itemLabelAlign}get itemLabelBaselineOffset(){return this._itemLabelBaselineOffset}set itemLabelBaselineOffset(e){typeof e=="number"?this._itemLabelBaselineOffset=e:this._itemLabelBaselineOffset=o.wheel.itemLabelBaselineOffset,this.resize()}get itemLabelColors(){return this._itemLabelColors}set itemLabelColors(e){Array.isArray(e)?this._itemLabelColors=e:this._itemLabelColors=o.wheel.itemLabelColors,this.processItems()}get itemLabelFont(){return this._itemLabelFont}set itemLabelFont(e){typeof e=="string"?this._itemLabelFont=e:this._itemLabelFont=o.wheel.itemLabelFont,this.resize()}get itemLabelFontSizeMax(){return this._itemLabelFontSizeMax}set itemLabelFontSizeMax(e){typeof e=="number"?this._itemLabelFontSizeMax=e:this._itemLabelFontSizeMax=o.wheel.itemLabelFontSizeMax}get itemLabelRadius(){return this._itemLabelRadius}set itemLabelRadius(e){typeof e=="number"?this._itemLabelRadius=e:this._itemLabelRadius=o.wheel.itemLabelRadius}get itemLabelRadiusMax(){return this._itemLabelRadiusMax}set itemLabelRadiusMax(e){typeof e=="number"?this._itemLabelRadiusMax=e:this._itemLabelRadiusMax=o.wheel.itemLabelRadiusMax}get itemLabelRotation(){return this._itemLabelRotation}set itemLabelRotation(e){typeof e=="number"?this._itemLabelRotation=e:this._itemLabelRotation=o.wheel.itemLabelRotation}get items(){return this._items}set items(e){Array.isArray(e)?this._items=e:this._items=o.wheel.items,this.processItems(),this.refreshCurrentIndex(this.getItemAngles(this.rotation))}get lineColor(){return this._lineColor}set lineColor(e){typeof e=="string"?this._lineColor=e:this._lineColor=o.wheel.lineColor}get lineWidth(){return this._lineWidth}set lineWidth(e){typeof e=="number"?this._lineWidth=e:this._lineWidth=o.wheel.lineWidth}get radius(){return this._radius}set radius(e){typeof e=="number"?this._radius=e:this._radius=o.wheel.radius,this.resize()}get rotation(){return this._rotation}set rotation(e){typeof e=="number"?this._rotation=e:this._rotation=o.wheel.rotation,this.refreshCurrentIndex(this.getItemAngles(this.rotation))}get rotationResistance(){return this._rotationResistance}set rotationResistance(e){typeof e=="number"?this._rotationResistance=e:this._rotationResistance=o.wheel.rotationResistance}get rotationSpeed(){return this._rotationSpeed}set rotationSpeed(e){if(typeof e=="number"){let t=Math.min(e,this.rotationSpeedMax);t=Math.max(t,-this.rotationSpeedMax),this.rotationDirection=this.getRotationDirection(t),this._rotationSpeed=t}else this.rotationDirection=0,this._rotationSpeed=o.wheel.rotationSpeed}get rotationSpeedMax(){return this._rotationSpeedMax}set rotationSpeedMax(e){typeof e=="number"?this._rotationSpeedMax=e:this._rotationSpeedMax=o.wheel.rotationSpeedMax}get offset(){return this._offset}set offset(e){e?this._offset=e:this._offset=o.wheel.offset,this.resize()}get onCurrentIndexChange(){return this._onCurrentIndexChange}set onCurrentIndexChange(e){typeof e=="function"?this._onCurrentIndexChange=e:this._onCurrentIndexChange=o.wheel.onCurrentIndexChange}get onRest(){return this._onRest}set onRest(e){typeof e=="function"?this._onRest=e:this._onRest=o.wheel.onRest}get onSpin(){return this._onSpin}set onSpin(e){typeof e=="function"?this._onSpin=e:this._onSpin=o.wheel.onSpin}get overlayImage(){return this._overlayImage}set overlayImage(e){typeof e=="string"?(this._overlayImage=new Image,this._overlayImage.src=e):this._overlayImage=o.wheel.overlayImage}get pointerRotation(){return this._pointerRotation}set pointerRotation(e){typeof e=="number"?this._pointerRotation=e:this._pointerRotation=o.wheel.pointerRotation}dragStart(e={x:0,y:0}){let t=b(e,this.canvas),i=-this.getAngleFromCenter(t);this.isDragging=!0,this.rotationSpeed=0,this.dragStartRotation=v(i,this.rotation),this.dragEvents=[{distance:0,x:t.x,y:t.y,now:performance.now()}],this.refreshCursor()}dragMove(e={x:0,y:0}){let t=b(e,this.canvas),i=this.getAngleFromCenter(t),s=this.dragEvents[0],r=this.getAngleFromCenter(s),a=S(r,i);this.dragEvents.unshift({distance:a,x:t.x,y:t.y,now:performance.now()}),this.debug&&this.dragEvents.length>=40&&this.dragEvents.pop(),this.rotation=v(i,this.dragStartRotation)}dragEnd(){this.isDragging=!1,clearInterval(this.dragClearOldDistances);let e=0,t=performance.now();for(let[i,s]of this.dragEvents.entries()){if(!this.isDragEventTooOld(t,s)){e+=s.distance;continue}this.dragEvents.length=i;break}e!==0&&this.spin(e*(1e3/_)),this.refreshCursor()}isDragEventTooOld(e,t={}){return e-t.now>_}};export{E as Wheel}; diff --git a/dist/spin-wheel-iife.js b/dist/spin-wheel-iife.js index c258859..fc85ad1 100644 --- a/dist/spin-wheel-iife.js +++ b/dist/spin-wheel-iife.js @@ -1,7 +1,7 @@ /** - * Spin Wheel (IIFE) v2.1.0 + * Spin Wheel (IIFE) v2.2.0 * https://github.com/CrazyTim/spin-wheel#readme * Copyright (c) CrazyTim 2022. * Distributed under the MIT License. */ -var wheel=(()=>{var R=Object.defineProperty;var b=Math.pow;var E=n=>R(n,"__esModule",{value:!0});var F=(n,t)=>{E(n);for(var e in t)R(n,e,{get:t[e],enumerable:!0})};var D={};F(D,{Wheel:()=>w});function _(n=0,t=0){return n=Math.ceil(n),t=Math.floor(t),Math.floor(Math.random()*(t-n))+n}function g(n=0){return n*Math.PI/180}function x(n,t){let e=0;for(let i of n){let o=i[t];o&&(e+=typeof o=="number"?o:1)}return e}function y(n,t,e){return t0?i=e%360:i=360+e%360,i===360&&(i=0),i}function z(n=0,t=0){let e=180-t,i=L(n,e);return 180-i}var c=-90,f=500,p=250,W=Object.freeze({left:"left",right:"right",center:"center"}),s=Object.freeze({borderColor:"#000",borderWidth:0,debug:!1,image:null,isInteractive:!0,itemBackgroundColor:"#fff",itemBackgroundColors:[],itemImage:null,itemImageSize:1,itemImageRadius:.5,itemLabel:"",itemLabelAlign:W.right,itemLabelBaselineOffset:0,itemLabelColor:"#000",itemLabelColors:[],itemLabelFont:"sans-serif",itemLabelFontSizeMax:f,itemLabelRadius:.85,itemLabelRadiusMax:.2,itemLabelRotation:0,itemWeight:1,items:[],lineColor:"#000",lineWidth:1,radius:.95,rotation:0,rotationResistance:-35,rotationSpeed:0,rotationSpeedMax:250,offset:{w:0,h:0},onCurrentIndexChange:null,onRest:null,onSpin:null,overlayImage:null,pointerRotation:0}),v=Object.freeze({pointerLineColor:"#ff00ff",labelOutlineColor:"#ff00ff",dragEventHue:200});function A(n={}){let t=n.canvas;"PointerEvent"in window?(t.addEventListener("pointerdown",o),t.addEventListener("pointermove",e)):(t.addEventListener("touchstart",u),t.addEventListener("mousedown",r),t.addEventListener("mousemove",i));function e(a={}){let l={x:a.clientX,y:a.clientY};n.isCursorOverWheel=n.wheelHitTest(l),n.refreshCursor()}function i(a={}){let l={x:a.clientX,y:a.clientY};n.isCursorOverWheel=n.wheelHitTest(l),n.refreshCursor()}function o(a={}){let l={x:a.clientX,y:a.clientY};if(!n.isInteractive||!n.wheelHitTest(l))return;a.preventDefault(),n.dragStart(l),t.setPointerCapture(a.pointerId),t.addEventListener("pointermove",m),t.addEventListener("pointerup",h),t.addEventListener("pointercancel",h);function m(d={}){d.preventDefault(),n.dragMove({x:d.clientX,y:d.clientY})}function h(d={}){d.preventDefault(),t.releasePointerCapture(d.pointerId),t.removeEventListener("pointermove",m),t.removeEventListener("pointerup",h),t.removeEventListener("pointercancel",h),n.dragEnd()}}function r(a={}){let l={x:a.clientX,y:a.clientY};if(!n.isInteractive||!n.wheelHitTest(l))return;n.dragStart(l),document.addEventListener("mousemove",m),document.addEventListener("mouseup",h);function m(d={}){d.preventDefault(),n.dragMove({x:d.clientX,y:d.clientY})}function h(d={}){d.preventDefault(),document.removeEventListener("mousemove",m),document.removeEventListener("mouseup",h),n.dragEnd()}}function u(a={}){let l={x:a.targetTouches[0].clientX,y:a.targetTouches[0].clientY};if(!n.isInteractive||!n.wheelHitTest(l))return;a.preventDefault(),n.dragStart(l),t.addEventListener("touchmove",m),t.addEventListener("touchend",h),t.addEventListener("touchcancel",h);function m(d={}){d.preventDefault(),n.dragMove({x:d.targetTouches[0].clientX,y:d.targetTouches[0].clientY})}function h(d={}){d.preventDefault(),t.removeEventListener("touchmove",m),t.removeEventListener("touchend",h),t.removeEventListener("touchcancel",h),n.dragEnd()}}}var w=class{constructor(t,e={}){this.canvasContainer=t,this.initCanvas(),this._borderColor=s.borderColor,this._borderWidth=s.borderWidth,this._debug=s.debug,this._image=s.image,this._isInteractive=s.isInteractive,this._itemBackgroundColors=s.itemBackgroundColors,this._itemLabelAlign=s.itemLabelAlign,this._itemLabelBaselineOffset=s.itemLabelBaselineOffset,this._itemLabelColors=s.itemLabelColors,this._itemLabelFont=s.itemLabelFont,this._itemLabelFontSizeMax=s.itemLabelFontSizeMax,this._itemLabelRadius=s.itemLabelRadius,this._itemLabelRadiusMax=s.itemLabelRadiusMax,this._itemLabelRotation=s.itemLabelRotation,this._items=s.items,this._lineColor=s.lineColor,this._lineWidth=s.lineWidth,this._rotationSpeedMax=s.rotationSpeedMax,this._radius=s.radius,this._rotation=s.rotation,this._rotationResistance=s.rotationResistance,this._rotationSpeed=s.rotationSpeed,this._offset=s.offset,this._onCurrentIndexChange=s.onCurrentIndexChange,this._onRest=s.onRest,this._onSpin=s.onSpin,this._overlayImage=s.overlayImage,this._pointerRotation=s.pointerRotation,e&&this.init(e)}initCanvas(){for(;this.canvasContainer.firstChild;)this.canvasContainer.removeChild(this.canvasContainer.firstChild);this.canvas=document.createElement("canvas"),this.canvasContainer.appendChild(this.canvas),this.context=this.canvas.getContext("2d"),this.registerEvents()}init(t={}){this.borderColor=t.borderColor,this.borderWidth=t.borderWidth,this.debug=t.debug,this.image=t.image,this.isInteractive=t.isInteractive,this.itemBackgroundColors=t.itemBackgroundColors,this.itemLabelAlign=t.itemLabelAlign,this.itemLabelBaselineOffset=t.itemLabelBaselineOffset,this.itemLabelColors=t.itemLabelColors,this.itemLabelFont=t.itemLabelFont,this.itemLabelFontSizeMax=t.itemLabelFontSizeMax,this.itemLabelRadius=t.itemLabelRadius,this.itemLabelRadiusMax=t.itemLabelRadiusMax,this.itemLabelRotation=t.itemLabelRotation,this.items=t.items,this.lineColor=t.lineColor,this.lineWidth=t.lineWidth,this.rotationSpeedMax=t.rotationSpeedMax,this.radius=t.radius,this.rotation=t.rotation,this.rotationResistance=t.rotationResistance,this.rotationSpeed=t.rotationSpeed,this.offset=t.offset,this.onCurrentIndexChange=t.onCurrentIndexChange,this.onRest=t.onRest,this.onSpin=t.onSpin,this.overlayImage=t.overlayImage,this.pointerRotation=t.pointerRotation,this.resize()}registerEvents(){window.addEventListener("resize",()=>this.resize()),A(this)}resize(){window.cancelAnimationFrame(this.frameRequestId);let[t,e]=[this.canvasContainer.clientWidth,this.canvasContainer.clientHeight],i=Math.min(t,e),o={w:i-i*this.offset.w,h:i-i*this.offset.h},r=Math.min(t/o.w,e/o.h);this.size=Math.max(o.w*r,o.h*r),this.canvas.style.width=t+"px",this.canvas.style.height=e+"px",this.canvas.width=t,this.canvas.height=e,this.center={x:t/2+t*this.offset.w,y:e/2+e*this.offset.h},this.actualRadius=this.size/2*this.radius,this.itemLabelFontSize=this.itemLabelFontSizeMax*(this.size/f),this.labelMaxWidth=this.actualRadius*(this.itemLabelRadius-this.itemLabelRadiusMax);for(let u of this.actualItems)this.itemLabelFontSize=Math.min(this.itemLabelFontSize,I(u.label,this.itemLabelFont,this.labelMaxWidth,this.context));this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}draw(t=0){let e=this.context;e.clearRect(0,0,this.canvas.width,this.canvas.height),this.lastFrame===void 0&&(this.lastFrame=t);let i=(t-this.lastFrame)/1e3;i>0&&(this.rotation+=i*this.rotationSpeed,this.rotation=this.rotation%360),this.lastFrame=t;let o=this.getItemAngles(this.rotation),r=this.borderWidth/f*this.size;for(let[a,l]of o.entries())e.beginPath(),e.moveTo(this.center.x,this.center.y),e.arc(this.center.x,this.center.y,this.actualRadius-r/2,g(l.start+c),g(l.end+c)),e.closePath(),e.fillStyle=this.actualItems[a].backgroundColor,e.fill();this.refreshCurrentIndex(o),this.drawItemLines(e,o),this.drawBorder(e),e.textBaseline="middle",e.textAlign=this.itemLabelAlign,e.font=this.itemLabelFontSize+"px "+this.itemLabelFont;let u=this.itemLabelFontSize*-this.itemLabelBaselineOffset;e.save();for(let[a,l]of o.entries()){let m=this.actualItems[a];if(!m.label)continue;e.save();let h=l.start+(l.end-l.start)/2;e.translate(this.center.x+Math.cos(g(h+c))*(this.actualRadius*this.itemLabelRadius),this.center.y+Math.sin(g(h+c))*(this.actualRadius*this.itemLabelRadius)),e.rotate(g(h+c)),this.debug&&(e.beginPath(),e.moveTo(0,0),e.lineTo(-this.labelMaxWidth,0),e.strokeStyle=v.labelOutlineColor,e.lineWidth=1,e.stroke(),e.strokeRect(0,-this.itemLabelFontSize/2,-this.labelMaxWidth,this.itemLabelFontSize)),e.rotate(g(this.itemLabelRotation)),e.fillStyle=m.labelColor,e.fillText(m.label,0,u),e.restore()}this.drawItemImages(e,o),this.drawImage(e,this.image,!1),this.drawImage(e,this.overlayImage,!0),this.drawPointerLine(e),this.drawDragEvents(e),this.applyDrag(i),this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}drawItemImages(t,e=[]){for(let[i,o]of e.entries()){let r=this.actualItems[i];if(!r.image||!r.image.complete||r.image.error)continue;t.save();let u=o.start+(o.end-o.start)/2;t.translate(this.center.x+Math.cos(g(u+c))*(this.actualRadius*r.imageRadius),this.center.y+Math.sin(g(u+c))*(this.actualRadius*r.imageRadius)),t.rotate(g(u));let a=this.size/500*r.image.width*r.imageSize,l=this.size/500*r.image.height*r.imageSize,m=-a/2,h=-l/2;t.drawImage(r.image,m,h,a,l),t.restore()}}drawImage(t,e,i=!1){if(!e)return;t.save(),t.translate(this.center.x,this.center.y),i||t.rotate(g(this.rotation));let o=i?this.size:this.size*this.radius,r=-(o/2);t.drawImage(e,r,r,o,o),t.restore()}drawPointerLine(t,e,i=!1){!this.debug||(t.save(),t.translate(this.center.x,this.center.y),t.rotate(g(this.pointerRotation+c)),t.beginPath(),t.moveTo(0,0),t.lineTo(this.actualRadius*2,0),t.strokeStyle=v.pointerLineColor,t.lineWidth=2,t.stroke(),t.restore())}drawBorder(t){let e=this.borderWidth/f*this.size;t.beginPath(),t.strokeStyle=this.borderColor,t.lineWidth=e,t.arc(this.center.x,this.center.y,this.actualRadius-e/2,0,2*Math.PI),t.stroke()}drawItemLines(t,e=[]){if(this.lineWidth<=0)return;let i=this.lineWidth/f*this.size;t.save(),t.translate(this.center.x,this.center.y);for(let[o,r]of e.entries())t.rotate(g(r.start+c)),t.beginPath(),t.moveTo(0,0),t.lineTo(this.actualRadius-i,0),t.strokeStyle=this.lineColor,t.lineWidth=i,t.stroke(),t.rotate(-g(r.start+c));t.restore()}drawDragEvents(){var e;if(!this.debug||!((e=this.dragEvents)==null?void 0:e.length))return;let t=[...this.dragEvents].reverse();for(let[i,o]of t.entries()){let r=i/this.dragEvents.length*100;ctx.beginPath(),ctx.arc(o.x,o.y,5,0,2*Math.PI),ctx.fillStyle=`hsl(${v.dragEventHue},100%,${r}%)`,ctx.strokeStyle="#000",ctx.lineWidth=.5,ctx.fill(),ctx.stroke()}}applyDrag(t=0){var i;if(this.rotationSpeed===0)return;let e=this.rotationSpeed+this.rotationResistance*t*this.rotationDirection;(this.rotationDirection===1&&e<0||this.rotationDirection===-1&&e>=0)&&(e=0),this.rotationSpeed=e,this.rotationSpeed===0&&((i=this.onRest)==null||i.call(this,{event:"rest",currentIndex:this._currentIndex}))}spin(t=0,e=0){var o;let i=e/2;this.rotationSpeed=_(t*(1-i),t*(1+i)),this.rotationSpeed!==0&&((o=this.onSpin)==null||o.call(this,{event:"spin",direction:this.rotationDirection,rotationSpeed:this.rotationSpeed}))}getRotationDirection(t=0){return t>0?1:-1}wheelHitTest(t={x:0,y:0}){let e=C(t,this.canvas);return S(e,this.center.x,this.center.y,this.actualRadius)}refreshCursor(){if(this.isDragging){this.canvas.style.cursor="grabbing";return}if(this.isInteractive&&this.isCursorOverWheel){this.canvas.style.cursor="grab";return}this.canvas.style.cursor=null}processItems(){this.actualItems=[];for(let[t,e]of this.items.entries()){let i={};typeof e.backgroundColor=="string"?i.backgroundColor=e.backgroundColor:this.itemBackgroundColors.length?i.backgroundColor=this.itemBackgroundColors[t%this.itemBackgroundColors.length]:i.backgroundColor=s.itemBackgroundColor,typeof e.label=="string"?i.label=e.label:i.label=s.itemLabel,typeof e.labelFont=="string"?i.labelFont=e.labelFont:i.labelFont=this.itemLabelFont,typeof e.labelColor=="string"?i.labelColor=e.labelColor:this.itemLabelColors.length?i.labelColor=this.itemLabelColors[t%this.itemLabelColors.length]:i.labelColor=s.itemLabelColor,typeof e.weight=="number"?i.weight=e.weight:i.weight=s.itemWeight,typeof e.image=="string"?(i.image=new Image,i.image.src=e.image,i.image.onerror=o=>(i.image.error=!0,!0)):i.image=s.itemImage,typeof e.imageSize=="number"?i.imageSize=e.imageSize:i.imageSize=s.itemImageSize,typeof e.imageRadius=="number"?i.imageRadius=e.imageRadius:i.imageRadius=s.itemImageRadius,this.actualItems.push(i)}this.actualItems.length?this.weightedItemAngle=360/x(this.actualItems,"weight"):this.weightedItemAngle=0}getAngleFromCenter(t={x:0,y:0}){return(M(this.center.x,this.center.y,t.x,t.y)+90)%360}getCurrentIndex(){return this._currentIndex}refreshCurrentIndex(t=[]){var e;for(let[i,o]of t.entries())if(!!y(this.pointerRotation,o.start%360,o.end%360)){if(this._currentIndex===i)break;this._currentIndex=i,(e=this.onCurrentIndexChange)==null||e.call(this,{event:"CurrentIndexChange",currentIndex:this._currentIndex})}}getItemAngles(t=0){let e=[],i,o=t;for(let r of this.actualItems)i=r.weight*this.weightedItemAngle,e.push({start:o,end:o+i}),o+=i;return e}get borderColor(){return this._borderColor}set borderColor(t){typeof t=="string"?this._borderColor=t:this._borderColor=s.borderColor}get borderWidth(){return this._borderWidth}set borderWidth(t){typeof t=="number"?this._borderWidth=t:this._borderWidth=s.borderWidth}get debug(){return this._debug}set debug(t){typeof t=="boolean"?this._debug=t:this._debug=s.debug}get image(){return this._image}set image(t){typeof t=="string"?(this._image=new Image,this._image.src=t):this._image=s.image}get isInteractive(){return this._isInteractive}set isInteractive(t){typeof t=="boolean"?this._isInteractive=t:this._isInteractive=s.isInteractive}get itemBackgroundColors(){return this._itemBackgroundColors}set itemBackgroundColors(t){Array.isArray(t)?this._itemBackgroundColors=t:this._itemBackgroundColors=s.itemBackgroundColors,this.processItems()}get itemLabelAlign(){return this._itemLabelAlign}set itemLabelAlign(t){typeof t=="string"?this._itemLabelAlign=t:this._itemLabelAlign=s.itemLabelAlign}get itemLabelBaselineOffset(){return this._itemLabelBaselineOffset}set itemLabelBaselineOffset(t){typeof t=="number"?this._itemLabelBaselineOffset=t:this._itemLabelBaselineOffset=s.itemLabelBaselineOffset,this.resize()}get itemLabelColors(){return this._itemLabelColors}set itemLabelColors(t){Array.isArray(t)?this._itemLabelColors=t:this._itemLabelColors=s.itemLabelColors,this.processItems()}get itemLabelFont(){return this._itemLabelFont}set itemLabelFont(t){typeof t=="string"?this._itemLabelFont=t:this._itemLabelFont=s.itemLabelFont,this.resize()}get itemLabelFontSizeMax(){return this._itemLabelFontSizeMax}set itemLabelFontSizeMax(t){typeof t=="number"?this._itemLabelFontSizeMax=t:this._itemLabelFontSizeMax=s.itemLabelFontSizeMax}get itemLabelRadius(){return this._itemLabelRadius}set itemLabelRadius(t){typeof t=="number"?this._itemLabelRadius=t:this._itemLabelRadius=s.itemLabelRadius}get itemLabelRadiusMax(){return this._itemLabelRadiusMax}set itemLabelRadiusMax(t){typeof t=="number"?this._itemLabelRadiusMax=t:this._itemLabelRadiusMax=s.itemLabelRadiusMax}get itemLabelRotation(){return this._itemLabelRotation}set itemLabelRotation(t){typeof t=="number"?this._itemLabelRotation=t:this._itemLabelRotation=s.itemLabelRotation}get items(){return this._items}set items(t){Array.isArray(t)?this._items=t:this._items=s.items,this.processItems()}get lineColor(){return this._lineColor}set lineColor(t){typeof t=="string"?this._lineColor=t:this._lineColor=s.lineColor}get lineWidth(){return this._lineWidth}set lineWidth(t){typeof t=="number"?this._lineWidth=t:this._lineWidth=s.lineWidth}get radius(){return this._radius}set radius(t){typeof t=="number"?this._radius=t:this._radius=s.radius,this.resize()}get rotation(){return this._rotation}set rotation(t){typeof t=="number"?this._rotation=t:this._rotation=s.rotation}get rotationResistance(){return this._rotationResistance}set rotationResistance(t){typeof t=="number"?this._rotationResistance=t:this._rotationResistance=s.rotationResistance}get rotationSpeed(){return this._rotationSpeed}set rotationSpeed(t){if(typeof t=="number"){let e=Math.min(t,this.rotationSpeedMax);e=Math.max(e,-this.rotationSpeedMax),this.rotationDirection=this.getRotationDirection(e),this._rotationSpeed=e}else this.rotationDirection=0,this._rotationSpeed=s.rotationSpeed}get rotationSpeedMax(){return this._rotationSpeedMax}set rotationSpeedMax(t){typeof t=="number"?this._rotationSpeedMax=t:this._rotationSpeedMax=s.rotationSpeedMax}get offset(){return this._offset}set offset(t){t?this._offset=t:this._offset=s.offset,this.resize()}get onCurrentIndexChange(){return this._onCurrentIndexChange}set onCurrentIndexChange(t){typeof t=="function"?this._onCurrentIndexChange=t:this._onCurrentIndexChange=s.onCurrentIndexChange}get onRest(){return this._onRest}set onRest(t){typeof t=="function"?this._onRest=t:this._onRest=s.onRest}get onSpin(){return this._onSpin}set onSpin(t){typeof t=="function"?this._onSpin=t:this._onSpin=s.onSpin}get overlayImage(){return this._overlayImage}set overlayImage(t){typeof t=="string"?(this._overlayImage=new Image,this._overlayImage.src=t):this._overlayImage=s.overlayImage}get pointerRotation(){return this._pointerRotation}set pointerRotation(t){typeof t=="number"?this._pointerRotation=t:this._pointerRotation=s.pointerRotation}dragStart(t={x:0,y:0}){let e=C(t,this.canvas),i=-this.getAngleFromCenter(e);this.isDragging=!0,this.rotationSpeed=0,this.dragStartRotation=L(i,this.rotation),this.dragEvents=[{distance:0,x:e.x,y:e.y,now:performance.now()}],this.refreshCursor()}dragMove(t={x:0,y:0}){let e=C(t,this.canvas),i=this.getAngleFromCenter(e),o=this.dragEvents[0],r=this.getAngleFromCenter(o),u=z(r,i);this.dragEvents.unshift({distance:u,x:e.x,y:e.y,now:performance.now()}),this.debug&&this.dragEvents.length>=40&&this.dragEvents.pop(),this.rotation=L(i,this.dragStartRotation)}dragEnd(){var i;this.isDragging=!1,clearInterval(this.dragClearOldDistances);let t=0,e=performance.now();for(let[o,r]of this.dragEvents.entries()){if(!this.isDragEventTooOld(e,r)){t+=r.distance;continue}this.dragEvents.length=o;break}t!==0&&(this.rotationSpeed=t*(1e3/p),(i=this.onSpin)==null||i.call(this,{event:"spin",rotationDirection:this.rotationDirection,rotationSpeed:this.rotationSpeed,dragEvents:[...this.dragEvents]})),this.refreshCursor()}isDragEventTooOld(t,e={}){return t-e.now>p}};return D;})(); +var wheel=(()=>{var L=Object.defineProperty;var f=Math.pow;var F=n=>L(n,"__esModule",{value:!0});var D=(n,e)=>{F(n);for(var t in e)L(n,t,{get:e[t],enumerable:!0})};var k={};D(k,{Wheel:()=>E});function p(n=0,e=0){return n=Math.ceil(n),e=Math.floor(e),Math.floor(Math.random()*(e-n))+n}function l(n=0){return n*Math.PI/180}function R(n,e){let t=0;for(let i of n){let s=i[e];s&&(t+=typeof s=="number"?s:1)}return t}function y(n,e,t){return e0?i=t%360:i=360+t%360,i===360&&(i=0),i}function w(n=0,e=0){let t=180-e,i=v(n,t);return 180-i}function M(n){return typeof n=="object"&&!Array.isArray(n)&&n!==null}var h=-90,m=500,_=250,W=Object.freeze({left:"left",right:"right",center:"center"}),o=Object.freeze({wheel:{borderColor:"#000",borderWidth:0,debug:!1,image:null,isInteractive:!0,itemBackgroundColors:[],itemLabelAlign:W.right,itemLabelBaselineOffset:0,itemLabelColors:[],itemLabelFont:"sans-serif",itemLabelFontSizeMax:m,itemLabelRadius:.85,itemLabelRadiusMax:.2,itemLabelRotation:0,items:[],lineColor:"#000",lineWidth:1,radius:.95,rotation:0,rotationResistance:-35,rotationSpeed:0,rotationSpeedMax:250,offset:{w:0,h:0},onCurrentIndexChange:null,onRest:null,onSpin:null,overlayImage:null,pointerRotation:0},item:{backgroundColor:"#fff",image:null,imageRadius:.5,imageSize:1,label:"",labelColor:"#000",weight:1}}),C=Object.freeze({pointerLineColor:"#ff00ff",labelOutlineColor:"#ff00ff",dragEventHue:200});function A(n={}){let e=n.canvas;n._handler_onPointerMoveRefreshCursor=(t={})=>{let i={x:t.clientX,y:t.clientY};n.isCursorOverWheel=n.wheelHitTest(i),n.refreshCursor()},n._handler_onMouseMoveRefreshCursor=(t={})=>{let i={x:t.clientX,y:t.clientY};n.isCursorOverWheel=n.wheelHitTest(i),n.refreshCursor()},n._handler_onPointerDown=(t={})=>{let i={x:t.clientX,y:t.clientY};if(!n.isInteractive||!n.wheelHitTest(i))return;t.preventDefault(),n.dragStart(i),e.setPointerCapture(t.pointerId),e.addEventListener("pointermove",s),e.addEventListener("pointerup",r),e.addEventListener("pointercancel",r);function s(a={}){a.preventDefault(),n.dragMove({x:a.clientX,y:a.clientY})}function r(a={}){a.preventDefault(),e.releasePointerCapture(a.pointerId),e.removeEventListener("pointermove",s),e.removeEventListener("pointerup",r),e.removeEventListener("pointercancel",r),n.dragEnd()}},n._handler_onMouseDown=(t={})=>{let i={x:t.clientX,y:t.clientY};if(!n.isInteractive||!n.wheelHitTest(i))return;n.dragStart(i),document.addEventListener("mousemove",s),document.addEventListener("mouseup",r);function s(a={}){a.preventDefault(),n.dragMove({x:a.clientX,y:a.clientY})}function r(a={}){a.preventDefault(),document.removeEventListener("mousemove",s),document.removeEventListener("mouseup",r),n.dragEnd()}},n._handler_onTouchStart=(t={})=>{let i={x:t.targetTouches[0].clientX,y:t.targetTouches[0].clientY};if(!n.isInteractive||!n.wheelHitTest(i))return;t.preventDefault(),n.dragStart(i),e.addEventListener("touchmove",s),e.addEventListener("touchend",r),e.addEventListener("touchcancel",r);function s(a={}){a.preventDefault(),n.dragMove({x:a.targetTouches[0].clientX,y:a.targetTouches[0].clientY})}function r(a={}){a.preventDefault(),e.removeEventListener("touchmove",s),e.removeEventListener("touchend",r),e.removeEventListener("touchcancel",r),n.dragEnd()}},"PointerEvent"in window?(e.addEventListener("pointerdown",n._handler_onPointerDown),e.addEventListener("pointermove",n._handler_onPointerMoveRefreshCursor)):(e.addEventListener("touchstart",n._handler_onTouchStart),e.addEventListener("mousedown",n._handler_onMouseDown),e.addEventListener("mousemove",n._handler_onMouseMoveRefreshCursor)),n._handler_onResize=n.resize.bind(n),window.addEventListener("resize",n._handler_onResize)}function z(n={}){let e=n.canvas;"PointerEvent"in window?(e.removeEventListener("pointerdown",n._handler_onPointerDown),e.removeEventListener("pointermove",n._handler_onPointerMoveRefreshCursor)):(e.removeEventListener("touchstart",n._handler_onTouchStart),e.removeEventListener("mousedown",n._handler_onMouseDown),e.removeEventListener("mousemove",n._handler_onMouseMoveRefreshCursor)),window.removeEventListener("resize",n._handler_onResize)}var E=class{constructor(e,t={}){if(!(e instanceof Element))throw"container parameter must be an Element";if(!M(t))throw"props parameter must be an Object";this.canvasContainer=e,this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.addCanvas(),A(this);for(let i of Object.keys(o.wheel))this["_"+i]=o.wheel[i];t&&this.init(o.wheel)}init(e={}){this._isInitialising=!0,this.borderColor=e.borderColor,this.borderWidth=e.borderWidth,this.debug=e.debug,this.image=e.image,this.isInteractive=e.isInteractive,this.itemBackgroundColors=e.itemBackgroundColors,this.itemLabelAlign=e.itemLabelAlign,this.itemLabelBaselineOffset=e.itemLabelBaselineOffset,this.itemLabelColors=e.itemLabelColors,this.itemLabelFont=e.itemLabelFont,this.itemLabelFontSizeMax=e.itemLabelFontSizeMax,this.itemLabelRadius=e.itemLabelRadius,this.itemLabelRadiusMax=e.itemLabelRadiusMax,this.itemLabelRotation=e.itemLabelRotation,this.items=e.items,this.lineColor=e.lineColor,this.lineWidth=e.lineWidth,this.rotationSpeedMax=e.rotationSpeedMax,this.radius=e.radius,this.rotation=e.rotation,this.rotationResistance=e.rotationResistance,this.rotationSpeed=e.rotationSpeed,this.offset=e.offset,this.onCurrentIndexChange=e.onCurrentIndexChange,this.onRest=e.onRest,this.onSpin=e.onSpin,this.overlayImage=e.overlayImage,this.pointerRotation=e.pointerRotation}addCanvas(){this.canvasContainer.appendChild(this.canvas)}removeCanvas(){this.canvasContainer.removeChild(this.canvas)}remove(){window.cancelAnimationFrame(this.frameRequestId),z(this),this.removeCanvas()}resize(){window.cancelAnimationFrame(this.frameRequestId);let[e,t]=[this.canvasContainer.clientWidth,this.canvasContainer.clientHeight],i=Math.min(e,t),s={w:i-i*this.offset.w,h:i-i*this.offset.h},r=Math.min(e/s.w,t/s.h);this.size=Math.max(s.w*r,s.h*r),this.canvas.style.width=e+"px",this.canvas.style.height=t+"px",this.canvas.width=e,this.canvas.height=t,this.center={x:e/2+e*this.offset.w,y:t/2+t*this.offset.h},this.actualRadius=this.size/2*this.radius,this.itemLabelFontSize=this.itemLabelFontSizeMax*(this.size/m),this.labelMaxWidth=this.actualRadius*(this.itemLabelRadius-this.itemLabelRadiusMax);for(let a of this.actualItems)this.itemLabelFontSize=Math.min(this.itemLabelFontSize,x(a.label,this.itemLabelFont,this.labelMaxWidth,this.context));this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}draw(e=0){let t=this.context;t.clearRect(0,0,this.canvas.width,this.canvas.height),this.lastFrame===void 0&&(this.lastFrame=e);let i=(e-this.lastFrame)/1e3;i>0&&(this.rotation+=i*this.rotationSpeed,this.rotation=this.rotation%360),this.lastFrame=e;let s=this.getItemAngles(this.rotation),r=this.borderWidth/m*this.size;for(let[u,d]of s.entries())t.beginPath(),t.moveTo(this.center.x,this.center.y),t.arc(this.center.x,this.center.y,this.actualRadius-r/2,l(d.start+h),l(d.end+h)),t.closePath(),t.fillStyle=this.actualItems[u].backgroundColor,t.fill();this.drawItemLines(t,s),this.drawBorder(t),t.textBaseline="middle",t.textAlign=this.itemLabelAlign,t.font=this.itemLabelFontSize+"px "+this.itemLabelFont;let a=this.itemLabelFontSize*-this.itemLabelBaselineOffset;t.save();for(let[u,d]of s.entries()){let g=this.actualItems[u];if(!g.label)continue;t.save();let c=d.start+(d.end-d.start)/2;t.translate(this.center.x+Math.cos(l(c+h))*(this.actualRadius*this.itemLabelRadius),this.center.y+Math.sin(l(c+h))*(this.actualRadius*this.itemLabelRadius)),t.rotate(l(c+h)),this.debug&&(t.beginPath(),t.moveTo(0,0),t.lineTo(-this.labelMaxWidth,0),t.strokeStyle=C.labelOutlineColor,t.lineWidth=1,t.stroke(),t.strokeRect(0,-this.itemLabelFontSize/2,-this.labelMaxWidth,this.itemLabelFontSize)),t.rotate(l(this.itemLabelRotation)),t.fillStyle=g.labelColor,t.fillText(g.label,0,a),t.restore()}this.drawItemImages(t,s),this.drawImage(t,this.image,!1),this.drawImage(t,this.overlayImage,!0),this.drawPointerLine(t),this.drawDragEvents(t),this.applyDrag(i),this._isInitialising=!1,this.frameRequestId=window.requestAnimationFrame(this.draw.bind(this))}drawItemImages(e,t=[]){for(let[i,s]of t.entries()){let r=this.actualItems[i];if(!r.image||!r.image.complete||r.image.error)continue;e.save();let a=s.start+(s.end-s.start)/2;e.translate(this.center.x+Math.cos(l(a+h))*(this.actualRadius*r.imageRadius),this.center.y+Math.sin(l(a+h))*(this.actualRadius*r.imageRadius)),e.rotate(l(a));let u=this.size/500*r.image.width*r.imageSize,d=this.size/500*r.image.height*r.imageSize,g=-u/2,c=-d/2;e.drawImage(r.image,g,c,u,d),e.restore()}}drawImage(e,t,i=!1){if(!t)return;e.save(),e.translate(this.center.x,this.center.y),i||e.rotate(l(this.rotation));let s=i?this.size:this.size*this.radius,r=-(s/2);e.drawImage(t,r,r,s,s),e.restore()}drawPointerLine(e,t,i=!1){!this.debug||(e.save(),e.translate(this.center.x,this.center.y),e.rotate(l(this.pointerRotation+h)),e.beginPath(),e.moveTo(0,0),e.lineTo(this.actualRadius*2,0),e.strokeStyle=C.pointerLineColor,e.lineWidth=2,e.stroke(),e.restore())}drawBorder(e){let t=this.borderWidth/m*this.size;e.beginPath(),e.strokeStyle=this.borderColor,e.lineWidth=t,e.arc(this.center.x,this.center.y,this.actualRadius-t/2,0,2*Math.PI),e.stroke()}drawItemLines(e,t=[]){if(this.lineWidth<=0)return;let i=this.lineWidth/m*this.size;e.save(),e.translate(this.center.x,this.center.y);for(let[s,r]of t.entries())e.rotate(l(r.start+h)),e.beginPath(),e.moveTo(0,0),e.lineTo(this.actualRadius-i,0),e.strokeStyle=this.lineColor,e.lineWidth=i,e.stroke(),e.rotate(-l(r.start+h));e.restore()}drawDragEvents(){var t;if(!this.debug||!((t=this.dragEvents)==null?void 0:t.length))return;let e=[...this.dragEvents].reverse();for(let[i,s]of e.entries()){let r=i/this.dragEvents.length*100;ctx.beginPath(),ctx.arc(s.x,s.y,5,0,2*Math.PI),ctx.fillStyle=`hsl(${C.dragEventHue},100%,${r}%)`,ctx.strokeStyle="#000",ctx.lineWidth=.5,ctx.fill(),ctx.stroke()}}applyDrag(e=0){var i;if(this.rotationSpeed===0)return;let t=this.rotationSpeed+this.rotationResistance*e*this.rotationDirection;(this.rotationDirection===1&&t<0||this.rotationDirection===-1&&t>=0)&&(t=0),this.rotationSpeed=t,this.rotationSpeed===0&&((i=this.onRest)==null||i.call(this,{event:"rest",currentIndex:this._currentIndex}))}spin(e=0,t=0){var s;let i=t/2;this.rotationSpeed=p(e*(1-i),e*(1+i)),this.dragEvents=[],this.rotationSpeed!==0&&((s=this.onSpin)==null||s.call(this,{event:"spin",direction:this.rotationDirection,rotationSpeed:this.rotationSpeed,dragEvents:[...this.dragEvents]}))}getRotationDirection(e=0){return e>0?1:-1}wheelHitTest(e={x:0,y:0}){let t=b(e,this.canvas);return I(t,this.center.x,this.center.y,this.actualRadius)}refreshCursor(){if(this.isDragging){this.canvas.style.cursor="grabbing";return}if(this.isInteractive&&this.isCursorOverWheel){this.canvas.style.cursor="grab";return}this.canvas.style.cursor=null}processItems(){this.actualItems=[];for(let[e,t]of this.items.entries()){let i={};typeof t.backgroundColor=="string"?i.backgroundColor=t.backgroundColor:this.itemBackgroundColors.length?i.backgroundColor=this.itemBackgroundColors[e%this.itemBackgroundColors.length]:i.backgroundColor=o.item.backgroundColor,typeof t.label=="string"?i.label=t.label:i.label=o.item.label,typeof t.labelFont=="string"?i.labelFont=t.labelFont:i.labelFont=this.itemLabelFont,typeof t.labelColor=="string"?i.labelColor=t.labelColor:this.itemLabelColors.length?i.labelColor=this.itemLabelColors[e%this.itemLabelColors.length]:i.labelColor=o.item.labelColor,typeof t.weight=="number"?i.weight=t.weight:i.weight=o.item.weight,typeof t.image=="string"?(i.image=new Image,i.image.src=t.image,i.image.onerror=s=>(i.image.error=!0,!0)):i.image=o.item.image,typeof t.imageSize=="number"?i.imageSize=t.imageSize:i.imageSize=o.item.imageSize,typeof t.imageRadius=="number"?i.imageRadius=t.imageRadius:i.imageRadius=o.item.imageRadius,this.actualItems.push(i)}this.actualItems.length?this.weightedItemAngle=360/R(this.actualItems,"weight"):this.weightedItemAngle=0}getAngleFromCenter(e={x:0,y:0}){return(S(this.center.x,this.center.y,e.x,e.y)+90)%360}getCurrentIndex(){return this._currentIndex}refreshCurrentIndex(e=[]){var t;this.actualItems.length===0&&(this._currentIndex=-1);for(let[i,s]of e.entries())if(!!y(this.pointerRotation,s.start%360,s.end%360)){if(this._currentIndex===i)break;this._currentIndex=i,this._isInitialising||(t=this.onCurrentIndexChange)==null||t.call(this,{event:"currentIndexChange",currentIndex:this._currentIndex});break}}getItemAngles(e=0){let t=[],i,s=e;for(let r of this.actualItems)i=r.weight*this.weightedItemAngle,t.push({start:s,end:s+i}),s+=i;return this.actualItems.length>1&&(t[t.length-1].end=t[0].start+360),t}get borderColor(){return this._borderColor}set borderColor(e){typeof e=="string"?this._borderColor=e:this._borderColor=o.wheel.borderColor}get borderWidth(){return this._borderWidth}set borderWidth(e){typeof e=="number"?this._borderWidth=e:this._borderWidth=o.wheel.borderWidth}get debug(){return this._debug}set debug(e){typeof e=="boolean"?this._debug=e:this._debug=o.wheel.debug}get image(){return this._image}set image(e){typeof e=="string"?(this._image=new Image,this._image.src=e):this._image=o.wheel.image}get isInteractive(){return this._isInteractive}set isInteractive(e){typeof e=="boolean"?this._isInteractive=e:this._isInteractive=o.wheel.isInteractive}get itemBackgroundColors(){return this._itemBackgroundColors}set itemBackgroundColors(e){Array.isArray(e)?this._itemBackgroundColors=e:this._itemBackgroundColors=o.wheel.itemBackgroundColors,this.processItems()}get itemLabelAlign(){return this._itemLabelAlign}set itemLabelAlign(e){typeof e=="string"?this._itemLabelAlign=e:this._itemLabelAlign=o.wheel.itemLabelAlign}get itemLabelBaselineOffset(){return this._itemLabelBaselineOffset}set itemLabelBaselineOffset(e){typeof e=="number"?this._itemLabelBaselineOffset=e:this._itemLabelBaselineOffset=o.wheel.itemLabelBaselineOffset,this.resize()}get itemLabelColors(){return this._itemLabelColors}set itemLabelColors(e){Array.isArray(e)?this._itemLabelColors=e:this._itemLabelColors=o.wheel.itemLabelColors,this.processItems()}get itemLabelFont(){return this._itemLabelFont}set itemLabelFont(e){typeof e=="string"?this._itemLabelFont=e:this._itemLabelFont=o.wheel.itemLabelFont,this.resize()}get itemLabelFontSizeMax(){return this._itemLabelFontSizeMax}set itemLabelFontSizeMax(e){typeof e=="number"?this._itemLabelFontSizeMax=e:this._itemLabelFontSizeMax=o.wheel.itemLabelFontSizeMax}get itemLabelRadius(){return this._itemLabelRadius}set itemLabelRadius(e){typeof e=="number"?this._itemLabelRadius=e:this._itemLabelRadius=o.wheel.itemLabelRadius}get itemLabelRadiusMax(){return this._itemLabelRadiusMax}set itemLabelRadiusMax(e){typeof e=="number"?this._itemLabelRadiusMax=e:this._itemLabelRadiusMax=o.wheel.itemLabelRadiusMax}get itemLabelRotation(){return this._itemLabelRotation}set itemLabelRotation(e){typeof e=="number"?this._itemLabelRotation=e:this._itemLabelRotation=o.wheel.itemLabelRotation}get items(){return this._items}set items(e){Array.isArray(e)?this._items=e:this._items=o.wheel.items,this.processItems(),this.refreshCurrentIndex(this.getItemAngles(this.rotation))}get lineColor(){return this._lineColor}set lineColor(e){typeof e=="string"?this._lineColor=e:this._lineColor=o.wheel.lineColor}get lineWidth(){return this._lineWidth}set lineWidth(e){typeof e=="number"?this._lineWidth=e:this._lineWidth=o.wheel.lineWidth}get radius(){return this._radius}set radius(e){typeof e=="number"?this._radius=e:this._radius=o.wheel.radius,this.resize()}get rotation(){return this._rotation}set rotation(e){typeof e=="number"?this._rotation=e:this._rotation=o.wheel.rotation,this.refreshCurrentIndex(this.getItemAngles(this.rotation))}get rotationResistance(){return this._rotationResistance}set rotationResistance(e){typeof e=="number"?this._rotationResistance=e:this._rotationResistance=o.wheel.rotationResistance}get rotationSpeed(){return this._rotationSpeed}set rotationSpeed(e){if(typeof e=="number"){let t=Math.min(e,this.rotationSpeedMax);t=Math.max(t,-this.rotationSpeedMax),this.rotationDirection=this.getRotationDirection(t),this._rotationSpeed=t}else this.rotationDirection=0,this._rotationSpeed=o.wheel.rotationSpeed}get rotationSpeedMax(){return this._rotationSpeedMax}set rotationSpeedMax(e){typeof e=="number"?this._rotationSpeedMax=e:this._rotationSpeedMax=o.wheel.rotationSpeedMax}get offset(){return this._offset}set offset(e){e?this._offset=e:this._offset=o.wheel.offset,this.resize()}get onCurrentIndexChange(){return this._onCurrentIndexChange}set onCurrentIndexChange(e){typeof e=="function"?this._onCurrentIndexChange=e:this._onCurrentIndexChange=o.wheel.onCurrentIndexChange}get onRest(){return this._onRest}set onRest(e){typeof e=="function"?this._onRest=e:this._onRest=o.wheel.onRest}get onSpin(){return this._onSpin}set onSpin(e){typeof e=="function"?this._onSpin=e:this._onSpin=o.wheel.onSpin}get overlayImage(){return this._overlayImage}set overlayImage(e){typeof e=="string"?(this._overlayImage=new Image,this._overlayImage.src=e):this._overlayImage=o.wheel.overlayImage}get pointerRotation(){return this._pointerRotation}set pointerRotation(e){typeof e=="number"?this._pointerRotation=e:this._pointerRotation=o.wheel.pointerRotation}dragStart(e={x:0,y:0}){let t=b(e,this.canvas),i=-this.getAngleFromCenter(t);this.isDragging=!0,this.rotationSpeed=0,this.dragStartRotation=v(i,this.rotation),this.dragEvents=[{distance:0,x:t.x,y:t.y,now:performance.now()}],this.refreshCursor()}dragMove(e={x:0,y:0}){let t=b(e,this.canvas),i=this.getAngleFromCenter(t),s=this.dragEvents[0],r=this.getAngleFromCenter(s),a=w(r,i);this.dragEvents.unshift({distance:a,x:t.x,y:t.y,now:performance.now()}),this.debug&&this.dragEvents.length>=40&&this.dragEvents.pop(),this.rotation=v(i,this.dragStartRotation)}dragEnd(){this.isDragging=!1,clearInterval(this.dragClearOldDistances);let e=0,t=performance.now();for(let[i,s]of this.dragEvents.entries()){if(!this.isDragEventTooOld(t,s)){e+=s.distance;continue}this.dragEvents.length=i;break}e!==0&&this.spin(e*(1e3/_)),this.refreshCursor()}isDragEventTooOld(e,t={}){return e-t.now>_}};return k;})(); diff --git a/package.json b/package.json index c3a7660..7d1f9bf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "spin-wheel", "displayName": "Spin Wheel", - "version": "2.1.0", + "version": "2.2.0", "type": "module", "scripts": { "start": "node scripts/build.js -entryPoint=src/wheel.js -serve",