UNPKG

lucky-wheel-component

Version:
186 lines (173 loc) 7.92 kB
'use strict'; var vue = require('vue'); var script = vue.defineComponent({ name: 'LuckyWheel', props: { // 奖品配置 prizes: { type: Array, required: true, default: () => [] }, // 抽奖次数 initialDrawCount: { type: Number, default: 3 }, // 转盘颜色配置 colors: { type: Array, default: () => ["#f31f49", "#fff7d7", "#a71d77"] }, // 文字颜色配置 textColors: { type: Array, default: () => ["#f3f1f1", "#a8213c", "#f3f1f1"] }, // 额外旋转圈数 additionalTurns: { type: Number, default: 10 }, // 提示文字配置 messages: { type: Object, default: () => ({ noChance: '您没有抽奖机会了' }) } }, data() { return { currentRotation: 0, isRotating: false, drawCount: this.initialDrawCount, lastClickTime: 0, lastRotation: 0 }; }, methods: { getPrizeStyle(index) { const perAngle = 360 / this.prizes.length; return { transform: `rotateZ(${perAngle / 2 - 90 + perAngle * index}deg)`, clipPath: this.getClipPath(perAngle) }; }, getClipPath(perAngle) { const p = perAngle / 2; const d = Math.tan(p * Math.PI / 180) * 100; const x = (100 - d) / 2; return `polygon(0% 50%, 100% ${x}%, 100% ${100 - x}%)`; }, startRotation() { // 防抖和状态检查 const now = Date.now(); if (now - this.lastClickTime < 1000 || this.isRotating || this.drawCount <= 0) { return; } this.lastClickTime = now; if (this.drawCount <= 0) { return; } this.isRotating = true; // 随机选择奖品 const prizeIndex = Math.floor(Math.random() * this.prizes.length); const targetAngle = this.getPrizeAngle(prizeIndex); // 计算旋转角度 const additionalRotation = 360 * this.additionalTurns; // 额外旋转10圈 const totalRotation = this.currentRotation - additionalRotation - targetAngle + this.lastRotation; // 应用旋转动画 const wheelElement = this.$refs.wheelRef; if (wheelElement) { wheelElement.style.transform = `rotate(${totalRotation}deg)`; } // 动画结束后处理 setTimeout(() => { this.isRotating = false; this.drawCount--; this.currentRotation = totalRotation; this.lastRotation = targetAngle; this.showResult(prizeIndex); }, 5000); // 触发事件 this.$emit('on-start', { prizeIndex, drawCount: this.drawCount }); }, getPrizeAngle(index) { const perAngle = 360 / this.prizes.length; return index * perAngle + perAngle / 2; }, showResult(prizeIndex) { const prize = this.prizes[prizeIndex]; this.$emit('on-complete', { index: prizeIndex, prize: prize }); } } }); const _hoisted_1 = { class: "lucky-wheel" }; const _hoisted_2 = { class: "wheel-box" }; const _hoisted_3 = { id: "wheel", ref: "wheelRef" }; const _hoisted_4 = { class: "wheel-inner" }; function render(_ctx, _cache, $props, $setup, $data, $options) { return (vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [ vue.createElementVNode("div", _hoisted_2, [ vue.createElementVNode("div", _hoisted_3, [ vue.createElementVNode("div", _hoisted_4, [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.prizes, (prize, index) => { return (vue.openBlock(), vue.createElementBlock("div", { key: index, class: "prize-part", style: vue.normalizeStyle(_ctx.getPrizeStyle(index)) }, [ vue.createElementVNode("div", { class: "prize-bg", style: vue.normalizeStyle({ background: _ctx.colors[index % _ctx.colors.length] }) }, null, 4 /* STYLE */), vue.createElementVNode("div", { class: "prize-text", style: vue.normalizeStyle({ color: _ctx.textColors[index % _ctx.textColors.length] }) }, vue.toDisplayString(prize.prize), 5 /* TEXT, STYLE */) ], 4 /* STYLE */)) }), 128 /* KEYED_FRAGMENT */)) ]) ], 512 /* NEED_PATCH */), vue.createElementVNode("div", { class: vue.normalizeClass(["pointer", { 'disabled': _ctx.drawCount === 0 }]), onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.startRotation && _ctx.startRotation(...args))) }, null, 2 /* CLASS */) ]) ])) } function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css_248z = "\r\n/* 复制原来的 CSS 样式并做适当调整 */\n.lucky-wheel[data-v-4f76abb5] {\r\n width: 100%;\r\n max-width: 600px;\r\n margin: 0 auto;\n}\n.wheel-box[data-v-4f76abb5] {\r\n width: 100%;\r\n padding-bottom: 100%;\r\n position: relative;\n}\n#wheel[data-v-4f76abb5] {\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n border-radius: 50%;\r\n overflow: hidden;\r\n background: url('./assets/wheel-bg.png') center center no-repeat;\r\n background-size: 100% 100%;\r\n transform-origin: center center;\r\n transition: transform 5s cubic-bezier(0.46, 0.03, 0, 0.96);\n}\r\n\r\n/* 转盘内部样式 */\n.wheel-inner[data-v-4f76abb5] {\r\n position: absolute;\r\n width: 83%;\r\n height: 83%;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n border-radius: 50%;\r\n overflow: hidden;\n}\n.prize-part[data-v-4f76abb5] {\r\n height: 100%;\r\n width: 50%;\r\n position: absolute;\r\n top: 0;\r\n left: 50%;\r\n transform-origin: left center;\r\n box-sizing: border-box;\n}\n.prize-bg[data-v-4f76abb5] {\r\n width: 100%;\r\n height: 100%;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\n}\n.prize-text[data-v-4f76abb5] {\r\n transform: translate(0, -50%) rotate(90deg);\r\n width: 100%;\r\n text-align: center;\r\n position: absolute;\r\n top: 50%;\r\n left: 20%;\r\n font-size: 1rem;\r\n padding-top: 0.3rem;\r\n box-sizing: border-box;\r\n white-space: nowrap;\r\n z-index: 1;\n}\n.pointer[data-v-4f76abb5] {\r\n position: absolute;\r\n left: 50%;\r\n top: 50%;\r\n transform: translate(-50%, -50%);\r\n width: 120px;\r\n height: 120px;\r\n background: url('./assets/game-arrow.png') center center no-repeat;\r\n background-size: contain;\r\n cursor: pointer;\r\n z-index: 2;\n}\n.pointer.disabled[data-v-4f76abb5] {\r\n cursor: not-allowed;\r\n opacity: 0.6;\n}\r\n"; styleInject(css_248z); script.render = render; script.__scopeId = "data-v-4f76abb5"; script.__file = "src/vue/LuckyWheel.vue"; module.exports = script;