vue-spin-the-wheel
Version:
Component "Wheel of Names" for Vue
216 lines (215 loc) • 7.49 kB
JavaScript
import { ref as C, computed as z, onMounted as _, onUpdated as $, watch as p, defineComponent as L, openBlock as R, createElementBlock as k, createElementVNode as P, normalizeStyle as T, unref as f, renderSlot as D, toDisplayString as F } from "vue";
function O(t, d) {
const c = [];
for (; t !== ""; ) {
let i = t.substr(0, d);
if (t.charAt(d) !== "" && t.charAt(d) !== " ") {
const e = i.lastIndexOf(" ");
e !== -1 && (i = i.substr(0, e));
}
t = t.replace(i, "").trim(), c.push(i);
}
return c;
}
const q = {
radius: 250,
// Radius of a circle
textRadius: 190,
// The distance between the prize location and the center of the circle
textLength: 6,
// Prize text 1 line of characters, maximum 2 lines
textDirection: "horizontal",
// Prize Text Direction
lineHeight: 20,
// Text line height
borderWidth: 0,
// Outer border of circle
borderColor: "transparent",
// The color of the outer border
btnText: "Spin",
// The text of the start button
btnWidth: 140,
// Button width
fontSize: 34
// Prize text font size
};
function Z(t) {
const d = C(), c = z(() => Object.assign(q, t.canvas || {}));
let i, e;
function g() {
if (i = d.value, i.getContext) {
const { radius: o, textRadius: r, borderWidth: n, borderColor: l, fontSize: v } = c.value;
if (!o || !r || !n || !l || !v)
throw new Error("radius, textRadius, borderWidth, borderColor, and fontSize are required");
const h = Math.PI / (t.prizes.length / 2);
e = i.getContext("2d"), e.clearRect(0, 0, o * 2, o * 2), e.strokeStyle = l, e.lineWidth = n * 2, e.font = `${v}px Arial`, t.prizes.forEach((u, m) => {
w(u, m, h, o, r, n);
});
}
}
function w(o, r, n, l, v, h = 0) {
const u = r * n - Math.PI / 2;
e.fillStyle = o.bgColor, e.beginPath(), e.arc(l, l, l - h, u, u + n, !1), e.stroke(), e.arc(l, l, 0, u + n, u, !0), e.fill(), e.save(), e.fillStyle = o.color, e.translate(l + Math.cos(u + n / 2) * v, l + Math.sin(u + n / 2) * v), S(u, n, o.name), e.restore();
}
function S(o, r, n) {
const { lineHeight: l, textLength: v, textDirection: h } = c.value;
if (!l || !v || !h)
throw new Error("lineHeight, textLength, and textDirection are required");
const u = O(n, v);
u && (h === "vertical" ? e.rotate(o + r / 2 + Math.PI) : e.rotate(o + r / 2 + Math.PI / 2), u.forEach((m, I) => x(m, I, h, l, u.length)));
}
function x(o, r, n, l, v = 0) {
let h = -e.measureText(o).width / 2, u = (r + 1) * l;
n === "vertical" && (h = 0, u = (r + 1) * l - v * l / 2), e.fillText(o, h, u);
}
return _(() => {
t.type === "canvas" && g();
}), $(() => {
t.type === "canvas" && g();
}), {
wheelEl: d,
canvasConfig: c,
drawCanvas: g
};
}
function j(t, d) {
const c = C(!1), i = C(0), e = C(), g = z(() => t.useWeight ? 100 : t.prizes.reduce((a, s) => a + (s.probability || 0), 0)), w = z(() => {
if (t.useWeight) return 0;
const a = [...t.prizes].sort((y, E) => {
const M = String(y.probability).split(".")[1], W = String(E.probability).split(".")[1], A = M ? M.length : 0;
return (W ? W.length : 0) - A;
}), s = String(a[0].probability).split(".")[1], b = s ? s.length : 0;
return [1, 10, 100, 1e3, 1e4][b > 4 ? 4 : b];
}), S = z(() => {
const a = [];
return t.prizes.forEach((s) => {
const b = t.useWeight ? s.weight || 0 : (s.probability || 0) * w.value;
console.log(a, b, t, s);
const y = new Array(b).fill(s.id);
a.push(...y);
}), a;
}), x = z(() => c.value ? t.duration / 1e3 : 0), o = z(() => ({
"-webkit-transform": `rotateZ(${i.value}deg)`,
transform: `rotateZ(${i.value}deg)`,
"-webkit-transition-duration": `${x.value}s`,
"transition-duration": `${x.value}s`,
"-webkit-transition-timing-function:": t.timingFun,
"transition-timing-function": t.timingFun
})), r = z(() => {
let a = t.angleBase * 360;
return t.angleBase < 0 && (a -= 360), a;
}), n = z(() => !t.disabled && !c.value && g.value === 100);
p(() => t.prizeId, (a) => {
if (!c.value) return;
let s = B(a);
t.angleBase < 0 && (s -= 360);
const b = i.value;
let y = t.angleBase * 360 + s;
const E = 360 * Math.floor((y - b) / 360);
t.angleBase >= 0 ? y += Math.abs(E) : y += -360 - E, i.value = y;
}), l();
function l() {
if (g.value !== 100)
throw new Error("Prizes Is Error: Sum of probabilities is not 100!");
return !0;
}
function v() {
if (n.value) {
if (t.verify) {
d("rotateStart", h);
return;
}
d("rotateStart"), h();
}
}
function h() {
c.value = !0;
const a = t.prizeId || I();
i.value = r.value + B(a);
}
function u() {
c.value = !1, i.value %= 360, d("rotateEnd", e.value);
}
function m(a, s) {
return a = Math.ceil(a), s = Math.floor(s), Math.floor(Math.random() * (s - a + 1)) + a;
}
function I() {
const a = S.value.length;
return S.value[m(0, a - 1)];
}
function B(a) {
const s = 360 / t.prizes.length, b = t.prizes.findIndex((y) => y.id === a);
return e.value = t.prizes[b], 360 - (s * b + s / 2);
}
return {
handleRotate: v,
rotateStyle: o,
onRotateEnd: u
};
}
const H = { class: "fw-container" }, N = ["width", "height"], U = { class: "fw-btn" }, V = /* @__PURE__ */ L({
__name: "index",
props: {
type: { default: "canvas" },
useWeight: { type: Boolean, default: !1 },
disabled: { type: Boolean, default: !1 },
canRotate: { type: Boolean, default: !1 },
verify: { type: Boolean, default: !1 },
canvas: null,
duration: { default: 6e3 },
timingFun: { default: "cubic-bezier(0.36, 0.95, 0.64, 1)" },
angleBase: { default: 10 },
prizeId: { default: 0 },
prizes: { default: () => [] }
},
emits: ["rotateStart", "rotateEnd"],
setup(t, { expose: d, emit: c }) {
const i = t, { wheelEl: e, canvasConfig: g } = Z(i), { handleRotate: w, rotateStyle: S, onRotateEnd: x } = j(i, c);
return d({
startRotate: () => {
console.log("startRotate"), w();
}
}), (o, r) => (R(), k("div", H, [
P("div", {
class: "fw-wheel",
style: T(f(S)),
onTransitionend: r[0] || (r[0] = //@ts-ignore
(...n) => f(x) && f(x)(...n)),
"on:webkitTransitionend": r[1] || (r[1] = //@ts-ignore
(...n) => f(x) && f(x)(...n))
}, [
t.type === "canvas" ? (R(), k("canvas", {
key: 0,
ref_key: "wheelEl",
ref: e,
width: (f(g).radius || 1) * 2,
height: (f(g).radius || 1) * 2
}, null, 8, N)) : D(o.$slots, "wheel", { key: 1 }, void 0, !0)
], 36),
P("div", U, [
t.type === "canvas" ? (R(), k("div", {
key: 0,
class: "fw-btn__btn",
style: T({ width: f(g).btnWidth + "px", height: f(g).btnWidth + "px" }),
onClick: r[2] || (r[2] = //@ts-ignore
(...n) => f(w) && f(w)(...n))
}, F(f(g).btnText), 5)) : (R(), k("div", {
key: 1,
class: "fw-btn__image",
onClick: r[3] || (r[3] = //@ts-ignore
(...n) => f(w) && f(w)(...n))
}, [
D(o.$slots, "button", {}, void 0, !0)
]))
])
]));
}
}), X = (t, d) => {
const c = t.__vccOpts || t;
for (const [i, e] of d)
c[i] = e;
return c;
}, J = /* @__PURE__ */ X(V, [["__scopeId", "data-v-45b073d4"]]);
export {
J as SpinTheWheel
};