幸运的数字转盘(Turntable)

爷,独闯天下 提交于 2020-02-06 12:24:54

幸运的数字转盘(Turntable)

示例

在这里插入图片描述

HTML

<h1>Give me a whack</h1>
<div id="spinner">
  <svg
       xmlns='http://www.w3.org/2000/svg'
       xmlns:xlink='http://www.w3.org/1999/xlink'
       viewBox='0 10 20 60'
       id="clicker"
       >
    <path d="M 3 20 Q 10 0 17 20 Q 10 100 3 20" fill="#ddd"  />
  </svg>


  <svg
       xmlns='http://www.w3.org/2000/svg'
       xmlns:xlink='http://www.w3.org/1999/xlink'
       viewBox='0 0 100 100'
       id="wheel"
       >


    <mask id="splineMask">
      <rect x="0" y="0" width="100" height="100" fill="white" />
      <path d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(36, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(72, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(108, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(144, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(180, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(216, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(252, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(288, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
      <path transform="rotate(324, 50, 50)" d="M48.5 33 Q 50 35 51.5 33 Q 50 18 48.5 33"/>
    </mask>


    <polygon points="50,50 71,-17 28,-16" style="fill: #FDD835"/>
    <polygon points="50,50 28,-16 -7,9" style="fill: #FFC107"/>
    <polygon points="50,50 -7,9 -20,51" style="fill: #FF9800"/>
    <polygon points="50,50 -20,51 -6,92" style="fill: #FF5722"/>
    <polygon points="50,50 -6,92 29,117" style="fill: #C2185B"/>
    <polygon points="50,50 29,117 72,116" style="fill: #7B1FA2"/>
    <polygon points="50,50 72,116 107,91" style="fill: #283593"/>
    <polygon points="50,50 107,91 120,49" style="fill: #2196F3"/>
    <polygon points="50,50 120,49 106,8" style="fill: #4CAF50"/>
    <polygon points="50,50 106,8,71,-17" style="fill: #8BC34A"/>


    <text x="45" y="14">1</text>
    <text x="45" y="14" transform="rotate(36, 50, 50)">2</text>
    <text x="45" y="14" transform="rotate(72, 50, 50)">3</text>
    <text x="45" y="14" transform="rotate(108, 50, 50)">4</text>
    <text x="45" y="14" transform="rotate(144, 50, 50)">5</text>
    <text x="45" y="14" transform="rotate(180, 50, 50)">6</text>
    <text x="45" y="14" transform="rotate(216, 50, 50)">7</text>
    <text x="45" y="14" transform="rotate(252, 50, 50)">8</text>
    <text x="45" y="14" transform="rotate(288, 50, 50)">9</text>
    <text x="40" y="14" transform="rotate(324, 50, 50)">10</text>


    <circle id="middle" cx="50" cy="50" r="33" mask="url(#splineMask)"/>
    <circle id="knob" cx="50" cy="50" r="12"/>
  </svg>


  <div id="shaddow"></div>
</div>

CSS

html{
	height: 100%;
}
body{
	background-color: #484848;
	height: 100%;
	margin: 0px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	font-family: Arial;
}


h1{
	color: white
}


#spinner{
	width: 400px;
	height: 400px;
	min-width: 400px;
	min-height: 400px;
	align-items: center;
	position: relative;
	overflow: hidden;
}


#clicker{
	position: absolute;
	top: 0px;
	left: calc(50% - 10px);
	width: 15px;
	height: 60px;
	z-index: 2;
	transform-origin: 50% 20px;
	pointer-events: none;
}


#wheel{
	position: absolute;
	top: 30px;
	left: 30px;
	width: calc(100% - 60px);
	height: calc(100% - 60px);
	box-sizing: border-box;
	border-radius: 100%;
	cursor: pointer;
	border: solid white 10px;
	will-change: transform;
	z-index: 1;
}


#shaddow{
	position: absolute;
	top: 30px;
	left: 30px;
	right: 30px;
	bottom: 30px;
	border-radius: 100%;
	box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
}


#splineMask > path{
	fill: black;
}


#wheel > #middle{
	fill: white;
}


#wheel > #knob{
	fill: #ddd;
}


#wheel > text{
	fill: white;
	font-weight: bold;
	-webkit-touch-callout: none;
    -webkit-user-select: none;
     -khtml-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
}


@media screen and ( max-height: 500px ) {
	h1{
		display: none;
	}
}

JS

class Wheel{
	constructor(){
		this.wheelElm = document.getElementById('wheel');
		this.wheelElm.addEventListener('mousedown', e =>{
			this.onGrab(e.clientX, e.clientY);
		});
		window.addEventListener('mousemove', e =>{
			if(e.which == 1)
				this.onMove(e.clientX, e.clientY);
			else if(!this.isDragging)
				this.onRelease()
			
		});
		window.addEventListener('mouseup', this.onRelease.bind(this));


		this.wheelElm.addEventListener('touchstart', e =>{
			this.onGrab(e.touches[0].clientX, e.touches[0].clientY);
		});
		window.addEventListener('touchmove', e =>{
			this.onMove(e.touches[0].clientX, e.touches[0].clientY);
		});
		window.addEventListener('touchend', this.onRelease.bind(this));


		this.calculatePositions();
		window.addEventListener('resize', this.calculatePositions.bind(this));


		this.currentAngle = 0;
		this.oldAngle = 0;
		this.lastAngles = [0,0,0];
		this.isDragging = false;
		this.startX = null;
		this.startY = null;


		this.positionCallbacks = [];
	}


	calculatePositions(){
		this.wheelWidth = this.wheelElm.getBoundingClientRect()['width'];
		this.wheelHeight = this.wheelElm.getBoundingClientRect()['height']
		this.wheelX = this.wheelElm.getBoundingClientRect()['x'] + this.wheelWidth / 2;
		this.wheelY = this.wheelElm.getBoundingClientRect()['y'] + this.wheelHeight / 2;
	}


	onPositionChange(callback){
		this.positionCallbacks.push(callback);
	}


	onGrab(x, y){
		if(!this.isSpinning){
			this.isDragging = true;
			this.startAngle = this.calculateAngle(x, y);
		}				
	}


	onMove(x, y){
		if(!this.isDragging)
			return


		this.lastAngles.shift();
		this.lastAngles.push(this.currentAngle);


		let deltaAngle = this.calculateAngle(x, y) - this.startAngle;
		this.currentAngle = deltaAngle + this.oldAngle;
		
		this.render(this.currentAngle);
	}


	calculateAngle(currentX, currentY){
		let xLength = currentX - this.wheelX;
		let yLength = currentY - this.wheelY;
		let angle = Math.atan2(xLength, yLength) * (180/Math.PI);
		return 365 - angle;
	}


	onRelease(){
		if(this.isDragging){
			this.isDragging = false;
			this.oldAngle = this.currentAngle;


			let speed = this.lastAngles[0] - this.lastAngles[2];
			this.giveMoment(speed);
		}		
	}


	giveMoment(speed){
		let maxSpeed = 30;
		if(speed >= maxSpeed)
			speed = maxSpeed;
		else if(speed <= -maxSpeed)
			speed = -maxSpeed;


		if(speed >= 0.1){
			speed -= 0.1;
			window.requestAnimationFrame(this.giveMoment.bind(this, speed));
			this.isSpinning = true;
		}
		else if(speed <= -0.1){
			speed += 0.1;
			window.requestAnimationFrame(this.giveMoment.bind(this, speed));
			this.isSpinning = true;
		}
		else{
			this.isSpinning = false;
		}


		this.oldAngle -= speed;
		this.render(this.oldAngle);
	}
	render(deg){
		this.wheelElm.style.transform = `rotate(${deg}deg)`;
		for(let callback of this.positionCallbacks){
			callback(deg);
		}
	}
}
let wheel = new Wheel();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!