UNPKG

flamingo-ui

Version:

火烈鸟UI组件库

286 lines (285 loc) 8.38 kB
import "./index-sfc.css"; import { ref, watch, onMounted, reactive } from "vue"; import { getPixelRatio } from "../utils/index"; const __vue_sfc__ = { props: { width: { type: String, required: true, default: "300px" }, height: { type: String, required: true, default: "300px" }, prizeList: { type: Array, required: true, default: () => [] }, prizeIndex: { type: Number, default: -1 }, turnsNumber: { type: Number, default: 5 }, styleOpt: { type: Object, default: () => ({ // 每一块扇形的背景色,默认值,可通过父组件来改变 prizeBgColors: [ "rgb(255, 231, 149)", "rgb(255, 247, 223)", "rgb(255, 231, 149)", "rgb(255, 247, 223)", "rgb(255, 231, 149)", "rgb(255, 247, 223)" ], // 每一块扇形的外边框颜色,默认值,可通过父组件来改变 borderColor: "#ff9800", borderSize: "1" }) }, turnsTime: { type: Number, // 转动需要持续的时间(秒) default: 5 }, lockTime: { type: Number, // 抽奖间隔(秒) default: 0 }, pointerStyle: { type: Object, default: () => ({ width: "90px", height: "117px", top: "45%", left: "50.5%", backgroundImage: 'url("https://gres.guopan.cn/png/20230314/turntable-point.png")', backgroundSize: "contain", backgroundRepeat: "no-repeat" }) } }, emits: ["click", "start-turns", "end-turns", "lock-turns"], setup(props, { emit }) { let { prizeList } = reactive(props); const { styleOpt, turnsTime, pointerStyle, turnsNumber, lockTime } = reactive(props); const lock = ref(false); const rorating = ref(false); const startRotateDegree = ref(0); const rotateAngle = ref("0"); const rotateTransition = ref(""); const turntableDom = ref(null); const canvasDom = ref(null); const getRotateAngle = (index) => { const angle = 360 / prizeList.length * index + 180 / prizeList.length; return { transform: `rotate(${angle}deg)` }; }; const init = () => { const data = styleOpt; const prizeNum = prizeList.length; const { prizeBgColors, borderColor, borderSize } = data; const canvas = canvasDom.value; const luckdraw = turntableDom.value; const ctx = canvas.getContext("2d"); const ratio = getPixelRatio(ctx); const canvasWidth = luckdraw.clientWidth * ratio; const canvasHeight = luckdraw.clientHeight * ratio; canvas.width = canvasWidth; canvas.height = canvasHeight; ctx.translate(canvasWidth / 2, canvasHeight / 2); ctx.rotate(-90 * Math.PI / 180); ctx.scale(1 / ratio, 1 / ratio); const radius = (Math.min(canvasWidth, canvasHeight) - borderSize * ratio) / 2; ctx.strokeStyle = borderColor; ctx.lineWidth = borderSize * ratio; for (let index = 0; index < prizeNum; index++) { ctx.save(); ctx.scale(ratio, ratio); const startAngle = index * Math.PI / (prizeNum / 2); const endAngle = (index + 1) * Math.PI / (prizeNum / 2); ctx.beginPath(); ctx.arc(0, 0, radius, startAngle, endAngle); ctx.lineTo(0, 0); ctx.closePath(); if (prizeList[index].prizeColor) { ctx.fillStyle = prizeList[index].prizeColor; } else { ctx.fillStyle = prizeBgColors[0]; } ctx.strokeStyle = borderColor; ctx.fill(); ctx.stroke(); ctx.restore(); } canvas.style.width = `${luckdraw.clientWidth}px`; canvas.style.height = `${luckdraw.clientHeight}px`; }; const canBeRotated = () => { if (lock.value) { if (!rorating.value) { emit("lock-turns"); } return false; } return true; }; const changeLock = () => { setTimeout(() => { lock.value = false; }, lockTime * 1e3); }; const rotate = (index) => { const turnsTimeNum = turnsTime; const rotateAngleValue = startRotateDegree.value + turnsNumber * 360 + 360 - (180 / prizeList.length + 360 / prizeList.length * index) - startRotateDegree.value % 360; startRotateDegree.value = rotateAngleValue; rotateAngle.value = `rotate(${rotateAngleValue}deg)`; rotateTransition.value = `transform ${turnsTimeNum}s cubic-bezier(0.250, 0.460, 0.455, 0.995)`; setTimeout(() => { emit("end-turns"); rorating.value = false; changeLock(); }, turnsTimeNum * 1e3 + 500); }; const startTurns = () => { if (!canBeRotated()) { return false; } emit("start-turns"); }; const rotateTurn = () => { lock.value = true; rorating.value = true; setTimeout(() => { rotate(props.prizeIndex); }, 300); }; onMounted(() => { init(); }); watch( () => props.prizeList, (list) => { prizeList = list; init(); } ); return { turntableDom, canvasDom, getRotateAngle, rotateAngle, rotateTransition, pointerStyle, startTurns, rotateTurn }; } }; import { createElementVNode as _createElementVNode, renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, toDisplayString as _toDisplayString, normalizeStyle as _normalizeStyle } from "vue"; const _hoisted_1 = { id: "canvas", ref: "canvasDom" }; const _hoisted_2 = { class: "prize" }; const _hoisted_3 = { class: "drawTable-name" }; const _hoisted_4 = ["src"]; function __vue_render__(_ctx, _cache) { return _openBlock(), _createElementBlock( "view", { class: "fmg-turn-table", ref: "turntableDom", style: _normalizeStyle({ width: _ctx.width, height: _ctx.height }) }, [ _createElementVNode( "view", { class: "turntable", style: _normalizeStyle({ transform: _ctx.rotateAngle, transition: _ctx.rotateTransition }) }, [ _createElementVNode( "canvas", _hoisted_1, " \u6D4F\u89C8\u5668\u7248\u672C\u8FC7\u4F4E ", 512 /* NEED_PATCH */ ), _createElementVNode("view", _hoisted_2, [ (_openBlock(true), _createElementBlock( _Fragment, null, _renderList(_ctx.prizeList, (item, index) => { return _openBlock(), _createElementBlock( "view", { class: "item", style: _normalizeStyle(_ctx.getRotateAngle(index)), key: item.id }, [ _createElementVNode( "view", _hoisted_3, _toDisplayString(item.prizeName), 1 /* TEXT */ ), _createElementVNode( "view", { class: "drawTable-img", style: _normalizeStyle({ width: item.width, height: item.height }) }, [ _createElementVNode("img", { src: item.prizeImg }, null, 8, _hoisted_4) ], 4 /* STYLE */ ) ], 4 /* STYLE */ ); }), 128 /* KEYED_FRAGMENT */ )) ]) ], 4 /* STYLE */ ), _createElementVNode( "view", { class: "pointer", style: _normalizeStyle(_ctx.pointerStyle), onClick: _cache[0] || (_cache[0] = (...args) => _ctx.startTurns && _ctx.startTurns(...args)) }, null, 4 /* STYLE */ ) ], 4 /* STYLE */ ); } __vue_sfc__.render = __vue_render__; var stdin_default = __vue_sfc__; export { stdin_default as default };