基于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>