simple-piano-keyboard
Version:
Can display simple piano keyboard. (Note: No include sound)
211 lines (210 loc) • 6.21 kB
JavaScript
import { toRefs as oe, watch as g, computed as r, ref as ae, openBlock as N, createElementBlock as b, normalizeStyle as h, createElementVNode as S, Fragment as ne, renderList as se, toDisplayString as re } from "vue";
const ie = (t, n) => {
const a = t.__vccOpts || t;
for (const [l, i] of n)
a[l] = i;
return a;
}, ce = 12, ue = 3, $ = {
C: 3,
"C#": 1.7,
D: 1.3,
"D#": 2.3,
E: 0.7,
F: 3,
"F#": 1.35,
G: 1.65,
"G#": 1.9,
A: 1.1,
"A#": 2.45,
B: 0.55
}, B = {
whiteKey: "#FFFFFF",
blackKey: "#222222",
selectedWhiteKey: "#B2EBF2",
selectedBlackKey: "#B2EBF2",
keyBorder: "#212121",
frameBorder: "#e0e0e0",
noteName: "#212121"
}, K = {
keyBorder: 1,
frameBorder: 2
}, _ = {
type: "none",
// none(default), intl, num
target: "A"
// A(default), B(# is not allowed), ... or all
}, de = {
name: "SimplePianoKeyboard",
props: {
modelValue: { default: [] },
lowestNote: { default: "A0" },
highestNote: { default: "C8" },
keyHeightSize: { default: 10 },
keyWidthSize: { default: 10 },
padding: { default: 8 },
width: { default: 380 },
color: {
default: B
},
thickness: {
default: K
},
noteNameDisplay: {
default: _
},
noteOutputType: { default: "intl" },
isReadOnly: { default: !1 }
},
emits: ["update:modelValue"],
setup(t, { emit: n }) {
const {
modelValue: a,
lowestNote: l,
highestNote: i,
keyHeightSize: p,
keyWidthSize: c,
padding: w,
width: H,
color: O,
thickness: F,
noteNameDisplay: z,
noteOutputType: P,
isReadOnly: I
} = oe(t);
g(a, (e, s) => {
(e.length !== s.length || e.some(
(o, k) => o !== s[k]
)) && (v.value = m());
});
const u = r(() => l.value || l.value === 0 ? isNaN(l.value) ? x(l.value) : l.value : 33), G = r(() => {
let e = 108;
return (i.value || i.value === 0) && (e = isNaN(i.value) ? x(i.value) : i.value), e < u.value && (e = u.value), e;
}), d = r(() => ({
height: ce * p.value,
width: ue * c.value
})), L = r(() => ({
height: d.value.height * 0.65,
width: d.value.width * 0.7
})), V = r(() => d.value.height * 0.76), y = r(
() => typeof O.value == "object" ? Object.assign(B, O.value) : B
), f = r(
() => typeof F.value == "object" ? Object.assign(K, F.value) : K
), q = r(
() => typeof z.value == "object" ? Object.assign(_, z.value) : _
), W = r(() => a.value && a.value.length > 0 ? a.value.map(
(e) => isNaN(e) ? x(e) : e
) : []), m = () => {
const e = [];
let s = 0;
e.push({
left: s,
isBlackKey: T(u.value),
selected: !!W.value.includes(u.value),
num: u.value,
intl: D(u.value)
});
for (let o = u.value + 1; o < G.value + 1; o++)
s += c.value * $[R(o)], e.push({
left: s,
isBlackKey: T(o),
selected: !!W.value.includes(o),
num: o,
intl: D(o),
char: R(o)
});
return e;
}, v = ae(m());
g(
v,
(e) => {
n(
"update:modelValue",
e.filter((s) => s.selected).map(
(s) => P.value === "intl" ? s.intl : s.num
)
);
},
{ deep: !0 }
), g([l, i], () => {
v.value = m();
});
const J = r(
() => v.value.filter((e) => !e.isBlackKey).length
), M = (e) => {
const { type: s, target: o } = q.value;
return s === "none" ? "" : e.char === o || o === "all" ? s === "intl" ? e.intl : e.num : "";
}, Q = (e) => {
I.value || (e.selected = !e.selected);
}, U = (e) => {
const { left: s, isBlackKey: o, selected: k } = e, { blackKey: Z, whiteKey: A, keyBorder: ee } = y.value, C = o ? L.value : d.value, te = o ? Z : A, le = o ? y.value.selectedBlackKey : y.value.selectedWhiteKey, j = f.value.keyBorder;
return `height: ${C.height}px; width: ${C.width}px; left: ${s}px; border: solid ${j}px ${ee}; border-radius: ${j * 3}px; background-color: ${k ? le : te}; z-index: ${o ? 2 : 1}`;
}, X = r(() => {
const e = f.value.keyBorder;
return `height: ${d.value.height + e * 2}px; width: ${d.value.width * J.value + e * 2}px; border-radius: ${e * 3}px; border: solid ${e}px ${y.value.keyBorder}`;
}), Y = r(() => {
const { frameBorder: e } = f.value;
return `width: ${H.value - e}px; padding: ${w.value}px; border: solid ${e}px ${y.value.frameBorder}; font-size: ${p.value * 1.4}px; color: ${y.value.noteName};`;
});
return {
spacerHeight: V,
keys: v,
getNoteName: M,
changeSelectionOfKey: Q,
keyStyle: U,
keysWrapperStyle: X,
keyboardWrapperStyle: Y
};
}
};
function D(t) {
const { char: n, num: a } = E(t);
return n + a;
}
function E(t) {
const n = Math.floor(t / 12), a = t % 12, l = a < 9 ? n - 1 : n;
return { char: Object.keys($)[a], num: l };
}
function x(t) {
const n = t.includes("#") ? t.slice(0, 2) : t.slice(0, 1), a = t.includes("#") ? Number(t.slice(2)) : Number(t.slice(1)), l = Object.keys($).indexOf(n);
return (l < 9 ? a + 1 : a) * 12 + l;
}
function T(t) {
const n = t % 12;
return [1, 3, 6, 8, 10].some((l) => l === n);
}
function R(t) {
const { char: n } = E(t);
return n;
}
const ye = ["onClick"], ve = { class: "note-name" };
function he(t, n, a, l, i, p) {
return N(), b("div", {
class: "keyboard-wrapper",
style: h(l.keyboardWrapperStyle)
}, [
S("div", {
class: "keys-wrapper",
style: h(l.keysWrapperStyle)
}, [
(N(!0), b(ne, null, se(l.keys, (c) => (N(), b("div", {
key: c.num,
style: h(l.keyStyle(c)),
onClick: (w) => l.changeSelectionOfKey(c),
class: "one-key"
}, [
S("div", {
style: h(`height: ${l.spacerHeight}px`)
}, null, 4),
S("div", ve, re(l.getNoteName(c)), 1)
], 12, ye))), 128))
], 4)
], 4);
}
const pe = /* @__PURE__ */ ie(de, [["render", he], ["__scopeId", "data-v-dc080436"]]), me = {
install: (t, n) => {
t.component("SimplePianoKeyboard", pe);
}
};
export {
me as default
};