flamingo-ui
Version:
火烈鸟UI组件库
286 lines (285 loc) • 8.38 kB
JavaScript
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
};