基于javascript的可以自定义设置圆几等份的抽奖示例

基于javascript的可以自定义设置圆几等份的抽奖示例

效果示例图

在这里插入图片描述

代码示例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			* {
				padding: 0px;
				margin: 0px;
				box-sizing: border-box;
			}

			.cricle-wrap {
				border: 1px solid red;
				border-radius: 50%;
				width: 400px;
				height: 400px;
				margin: 50px auto;
				position: relative;
			}

			.min-cricle {
				border-radius: 50%;
				width: 10px;
				height: 10px;
				background-color: red;
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
			}

			.cricle-line {
				width: 50%;
				height: 1px;
				background-color: red;
				position: absolute;
				top: 50%;
				left: 50%;
				/*
				* 默认情况下,元素的动作参考点为元素盒子的中心 
				* 使用transform-origin改变元素原点位置
				* :center center (正中)它以我的线的中间为圆点,进行旋转
				* :left center (靠左居中) 它以我的线的左边为圆点,进行旋转,即我的线的最左点是固定的,来旋转
				* :right center (靠右居中) 它以我的线的左右边为圆点,进行旋转,即我的线的最右点是固定的,来旋转
				*/
				transform-origin: left center;
			}

			.cricle-angle {
				width: 50%;
				height: 0;
				position: absolute;
				top: 50%;
				left: 50%;
				transform-origin: left center;
			}

			.cricle-angle-children {
				width: 100%;
				height: 100%;
				position: relative;
			}

			.grandson {
				border: 1px solid red;
				width: 50px;
				height: 30px;
				position: absolute;
				top: 50%;
				transform: translateY(-50%) rotate(90deg);
				text-align: center;
				line-height: 30px;
				font-size: 12px;
			}

			.arrow {
				border: 1px solid red;
				border-radius: 50%;
				width: 60px;
				height: 60px;
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%) rotate(0deg);
				line-height: 60px;
				text-align: center;
				z-index: 1;
				background-color: #fff;
				background-image: url("img/arrow.png");
				background-position: center;
				background-repeat: no-repeat;
				background-size: 100% 100%;
			}

			.add-transition {
				transition: all 3s ease-in-out;
			}

			#draw {
				display: block;
				width: 100px;
				height: 40px;
				margin: 12px auto;
			}
		</style>
	</head>
	<body>
		<div class="cricle-wrap" id="cricle">
			<!-- 圆点 -->
			<div class="min-cricle"></div>
			<!-- 箭头 -->
			<div class="arrow"></div>
		</div>
		<button id="draw">抽检</button>

	</body>
	<script type="text/javascript">
		const options = {
			cricleBox: document.querySelector("#cricle"), //获取当前圆
			count: 9, //圆被均等分成n份
			radius: 200, //圆的半径
			prizeDisc: 10, //奖品所在位置0-50,值越小,距离圆心越远
		}
		turntable();

		function turntable() {

			//每一块的弧度
			const angle = 360 / options.count;
			for (let i = 0; i < options.count; i++) {
				let rotateAngle = i * angle;
				const scaleMark = createScaleMark(rotateAngle)
				options.cricleBox.appendChild(scaleMark);
				const prize = createPrize(rotateAngle, angle, i);
				options.cricleBox.appendChild(prize);
			}
			/**
			 * 创建刻度线
			 * **/
			function createScaleMark(rotateAngle) {
				const divs = document.createElement("div");
				divs.classList.add("cricle-line");
				divs.style.transform = `rotate(${rotateAngle-90}deg)`
				return divs
			}
			/**
			 * 创建奖品块
			 * **/
			function createPrize(rotateAngle, skewAngle, i) {
				const prizes = document.createElement("div");
				prizes.classList.add("cricle-angle");

				const childrenDIvs = document.createElement("div");
				childrenDIvs.classList.add("cricle-angle-children");

				const grandson = document.createElement("div");
				grandson.classList.add("grandson");
				grandson.style.right = `${options.prizeDisc}%`
				grandson.innerText = (i + 1) + '等奖';

				childrenDIvs.appendChild(grandson)

				prizes.appendChild(childrenDIvs)
				prizes.style.transform = `rotate(${rotateAngle-90+(skewAngle/2)}deg)`
				return prizes
			}

		}
		//中奖号码
		let winningNumber = 0;
		//箭头旋转的角度
		let rotate = 0;
		//点击抽奖按钮
		const arrow = document.querySelector(".arrow");
		document.querySelector("#draw").addEventListener("click", () => {
			winningNumber = Math.floor(Math.random() * options.count) + 1;
			rotateTurntable(winningNumber);
		})

		function rotateTurntable(n) {
			//每一块的弧度
			const angle = 360 / options.count;
			const skewAngle = angle / 2;
			rotate += n * angle - skewAngle + 360 * 10 + (360 - rotate % 360);
			arrow.classList.add("add-transition");
			arrow.style.transform = `translate(-50%, -50%) rotate(${rotate}deg)`;
		}
		//监听动画是否结束
		arrow.addEventListener("transitionend", () => {
			console.log("[动画结束]")
			console.log("[中奖号码]", winningNumber)
			arrow.classList.remove("add-transition");
			arrow.style.transform = `translate(-50%, -50%) rotate(${rotate}deg)`;
		})
	</script>
</html>

使用class

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			* {
				padding: 0px;
				margin: 0px;
				box-sizing: border-box;
			}

			.cricle-wrap {
				border: 1px solid red;
				border-radius: 50%;
				width: 400px;
				height: 400px;
				margin: 50px auto;
				position: relative;
			}

			.min-cricle {
				border-radius: 50%;
				width: 10px;
				height: 10px;
				background-color: red;
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
			}

			.cricle-line {
				width: 50%;
				height: 1px;
				background-color: red;
				position: absolute;
				top: 50%;
				left: 50%;
				/*
				* 默认情况下,元素的动作参考点为元素盒子的中心 
				* 使用transform-origin改变元素原点位置
				* :center center (正中)它以我的线的中间为圆点,进行旋转
				* :left center (靠左居中) 它以我的线的左边为圆点,进行旋转,即我的线的最左点是固定的,来旋转
				* :right center (靠右居中) 它以我的线的左右边为圆点,进行旋转,即我的线的最右点是固定的,来旋转
				*/
				transform-origin: left center;
			}

			.cricle-angle {
				width: 50%;
				height: 0;
				position: absolute;
				top: 50%;
				left: 50%;
				transform-origin: left center;
			}

			.cricle-angle-children {
				width: 100%;
				height: 100%;
				position: relative;
			}

			.grandson {
				border: 1px solid red;
				width: 50px;
				height: 30px;
				position: absolute;
				top: 50%;
				transform: translateY(-50%) rotate(90deg);
				text-align: center;
				line-height: 30px;
				font-size: 12px;
			}

			.arrow {
				border: 1px solid red;
				border-radius: 50%;
				width: 60px;
				height: 60px;
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%) rotate(0deg);
				line-height: 60px;
				text-align: center;
				z-index: 1;
				background-color: #fff;
				background-image: url("img/arrow.png");
				background-position: center;
				background-repeat: no-repeat;
				background-size: 100% 100%;
			}

			.add-transition {
				transition: all 3s ease-in-out;
			}

			#draw {
				display: block;
				width: 100px;
				height: 40px;
				margin: 12px auto;
			}
		</style>
	</head>
	<body>
		<div class="cricle-wrap" id="cricle">
			<!-- 圆点 -->
			<div class="min-cricle"></div>
			<!-- 箭头 -->
			<div class="arrow"></div>
		</div>
		<button id="draw">抽检</button>
	</body>
	<script type="text/javascript">
		class Turntable {
			//中奖号码
			winningNumber = 0;
			//箭头旋转的角度
			rotate = 0;
			static OPTIONS = {
				cricleBox: document.querySelector("#cricle"), //获取当前圆
				arrow: document.querySelector(".arrow"), //箭头的按钮
				prizeBtn: document.querySelector("#draw"), //抽奖按钮
				count: 5, //圆被均等分成n份
				radius: 200, //圆的半径
				prizeDisc: 10, //奖品所在位置0-50,值越小,距离圆心越远
				success: null
			}
			constructor(options) {
				this.options = Object.assign({}, Turntable.OPTIONS, options);
				this.init();
			}

			init() {
				//每一块的弧度
				const angle = 360 / this.options.count;
				for (let i = 0; i < this.options.count; i++) {
					let rotateAngle = i * angle;
					const scaleMark = this.createScaleMark(rotateAngle)
					this.options.cricleBox.appendChild(scaleMark);
					const prize = this.createPrize(rotateAngle, angle, i);
					this.options.cricleBox.appendChild(prize);
				}
				this.clickEvent();
			}
			/**
			 * 创建刻度线
			 * rotateAngle :旋转的角度
			 * **/
			createScaleMark(rotateAngle) {
				const divs = document.createElement("div");
				divs.classList.add("cricle-line");
				divs.style.transform = `rotate(${rotateAngle-90}deg)`
				return divs
			}
			/**
			 * 创建奖品块
			 * rotateAngle :旋转的角度
			 * skewAngle:偏移量的角度
			 * **/
			createPrize(rotateAngle, skewAngle, i) {
				const prizes = document.createElement("div");
				prizes.classList.add("cricle-angle");

				const childrenDIvs = document.createElement("div");
				childrenDIvs.classList.add("cricle-angle-children");

				const grandson = document.createElement("div");
				grandson.classList.add("grandson");
				grandson.style.right = `${this.options.prizeDisc}%`
				grandson.innerText = (i + 1) + '等奖';

				childrenDIvs.appendChild(grandson)

				prizes.appendChild(childrenDIvs)
				prizes.style.transform = `rotate(${rotateAngle-90+(skewAngle/2)}deg)`
				return prizes
			}
			/**
			 * 点击抽奖,事件处理
			 * **/
			clickEvent() {
				this.options.prizeBtn.addEventListener("click", () => {
					this.winningNumber = Math.floor(Math.random() * this.options.count) + 1;
					this.rotateTurntable(this.winningNumber);
				})

				//监听动画是否结束
				this.options.arrow.addEventListener("transitionend", () => {
					console.log("[动画结束]")
					this.options.arrow.classList.remove("add-transition");
					this.options.arrow.style.transform = `translate(-50%, -50%) rotate(${this.rotate}deg)`;

					this.options.success && this.options.success(this.winningNumber)
				})
			}
			/**
			 * 转动箭头到指定奖品
			 * **/
			rotateTurntable(n) {
				//每一块的弧度
				const angle = 360 / this.options.count;
				const skewAngle = angle / 2;
				this.rotate += n * angle - skewAngle + 360 * 10 + (360 - this.rotate % 360);
				this.options.arrow.classList.add("add-transition");
				this.options.arrow.style.transform = `translate(-50%, -50%) rotate(${this.rotate}deg)`;
			}
		}
		new Turntable({
			cricleBox: document.querySelector("#cricle"), //获取当前圆
			arrow: document.querySelector(".arrow"), //箭头的按钮
			prizeBtn: document.querySelector("#draw"), //抽奖按钮
			count: 9, //圆被均等分成n份
			radius: 200, //圆的半径
			prizeDisc: 10, //奖品所在位置0-50,值越小,距离圆心越远
			success: (response) => {
				console.log(`${response}等奖`)
			}
		});
	</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值