index.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { defineComponent, onMounted, onUnmounted, reactive } from "vue";
  2. import styles from "./index.module.less";
  3. export default defineComponent({
  4. name: "Keys",
  5. emits: ["click"],
  6. props: {
  7. show: {
  8. type: Boolean,
  9. default: false,
  10. },
  11. },
  12. setup(props, { emit }) {
  13. const data = reactive({
  14. keys: [
  15. { key: "C", singname: "do", type: "white" },
  16. { key: "D", singname: "re", type: "white" },
  17. { key: "E", singname: "mi", type: "white" },
  18. { key: "F", singname: "fa", type: "white" },
  19. { key: "G", singname: "so", type: "white" },
  20. { key: "A", singname: "la", type: "white" },
  21. { key: "B", singname: "si", type: "white" },
  22. ],
  23. keyDown: "",
  24. });
  25. /** 赤橙黄露青蓝紫 */
  26. const colors = ["#F07C83", "#FF966C", "#FBB957", "#A7DCBF", "#CCCCD6", "#A5D2FF", "#B0A4F4"];
  27. const productKey = (total = 0) => {
  28. return new Array(Math.abs(total)).fill(total > 0 ? "'" : ",").join("");
  29. };
  30. const keyDown = (e: KeyboardEvent) => {
  31. data.keyDown = e.key.toLocaleUpperCase();
  32. };
  33. const keyUp = (e: KeyboardEvent) => {
  34. data.keyDown = "";
  35. };
  36. onMounted(() => {
  37. document.addEventListener("keydown", keyDown);
  38. document.addEventListener("keyup", keyUp);
  39. });
  40. onUnmounted(() => {
  41. document.removeEventListener("keydown", keyDown);
  42. document.removeEventListener("keyup", keyUp);
  43. });
  44. return () => (
  45. <div class={[styles.piano, props.show && styles.show]}>
  46. {new Array(7).fill(0).map((_, index) => (
  47. <div class={styles.pianoItemWrap}>
  48. {data.keys.map((item) => {
  49. return (
  50. <div
  51. class={[styles.item, index === 3 && data.keyDown === item.key && styles.keyDown]}
  52. key={index}
  53. onClick={() => {
  54. let key = index > 3 ? item.key.toLocaleLowerCase() : item.key;
  55. emit("click", {
  56. type: "note",
  57. value: key + productKey([3, 4].includes(index) ? 0 : index - 3),
  58. });
  59. }}
  60. >
  61. <div class={styles.keytip}>
  62. <div style={{ color: "#ff4a00" }}>
  63. {index === 3 && item.key === "C" ? "中央C" : ""}
  64. </div>
  65. <div class={styles.keyname}>
  66. {item.key}
  67. {index + 1}
  68. </div>
  69. <div class={styles.singname} style={{ background: colors[index] }}>
  70. {item.singname}
  71. </div>
  72. </div>
  73. </div>
  74. );
  75. })}
  76. <div class={styles.bkeyWrap}>
  77. {data.keys.map((item) => {
  78. if (item.key === "E" || item.key === "B") return null;
  79. return (
  80. <div
  81. class={styles.bkey}
  82. onClick={() => {
  83. let key = index > 3 ? item.key.toLocaleLowerCase() : item.key;
  84. emit("click", {
  85. type: "note",
  86. value: key + productKey([3, 4].includes(index) ? 0 : index - 3) + "-" + "^",
  87. });
  88. }}
  89. >
  90. <div class="keytip"></div>
  91. </div>
  92. );
  93. })}
  94. </div>
  95. </div>
  96. ))}
  97. </div>
  98. );
  99. },
  100. });