liushengqiang 1 рік тому
батько
коміт
9fd49128ac

+ 58 - 48
src/pc/component/keys/index.module.less

@@ -16,15 +16,28 @@
 
 .pianoItemWrap {
     position: relative;
-    display: flex;
     flex: 1;
-    background-color: #ddd;
+    display: flex;
+    justify-content: center;
+    margin: 0 auto;
+    overflow: hidden;
+
+    .itemWrap {
+        position: relative;
+        display: flex;
+        width: calc(100% / 7);
+        max-width: 280px;
+        // background-color: #ddd;
+        // box-shadow: 0 0 5px 0 #ccc;
+        &:first-child{
+            justify-content: flex-end;
+        }
+    }
 
     .item {
         position: relative;
         width: calc(100% / 7);
-        padding-bottom: 80%;
-        margin: 0;
+        height: 180px;
         background: #fff;
         background: linear-gradient(-30deg, #f5f5f5, #fff);
         border: 1px solid #ccc;
@@ -43,6 +56,7 @@
             background: #efefef;
             transform: scaleY(0.95);
             transform-origin: top;
+
             &::before {
                 content: "";
                 position: absolute;
@@ -50,16 +64,17 @@
                 bottom: 0;
                 width: 10%;
                 height: 100%;
-                background: rgba(0,0,0,.1);
+                background: rgba(0, 0, 0, .1);
             }
-            &::after{
+
+            &::after {
                 content: "";
                 position: absolute;
                 right: 0;
                 bottom: 0;
                 width: 10%;
                 height: 100%;
-                background: rgba(0,0,0,.1);
+                background: rgba(0, 0, 0, .1);
             }
         }
     }
@@ -86,54 +101,49 @@
         border-radius: 2px;
     }
 
-    .bkeyWrap {
+    .bkey {
         position: absolute;
-        width: 100%;
-        padding-bottom: 50%;
-        top: 0;
-
-        .bkey {
-            width: 10%;
-            height: 100%;
-            background: linear-gradient(-20deg, #333, #000, #333);
-            border-color: #666 #222 #111 #555;
-            border-style: solid;
-            border-width: 1px 2px 7px;
-            border-radius: 0 0 2px 2px;
-            box-shadow: inset 0 -1px 2px hsla(0, 0%, 100%, .4), 0 2px 3px rgba(0, 0, 0, .4);
-            position: absolute;
-            top: 0;
-            overflow: hidden;
-
-            &:first-child {
-                left: 9%;
-            }
+        width: calc(100% / 8);
+        height: 100px;
+        background: linear-gradient(-20deg, #333, #000, #333);
+        border-color: #666 #222 #111 #555;
+        border-style: solid;
+        border-width: 1px 2px 7px;
+        border-radius: 0 0 2px 2px;
+        box-shadow: inset 0 -1px 2px hsla(0, 0%, 100%, .4), 0 2px 3px rgba(0, 0, 0, .4);
+        overflow: hidden;
+        z-index: 2;
 
-            &:nth-child(2) {
-                left: 24%;
-            }
+        &:hover {
+            cursor: pointer;
+            box-shadow: inset 0 0 7px 0 #87cefa;
+        }
 
-            &:nth-child(3) {
-                left: 52%;
-            }
+        &:active {
+            background: #75c3ed;
+            border-color: #75c3ed;
+        }
+    }
 
-            &:nth-child(4) {
-                left: 66%;
-            }
+    :global {
+        .bkey0 {
+            left: 8%;
+        }
 
-            &:nth-child(5) {
-                left: 81%;
-            }
+        .bkey1 {
+            left: 23%;
+        }
 
-            &:hover {
-                cursor: pointer;
-                box-shadow: inset 0 0 7px 0 #87cefa;
-            }
+        .bkey3 {
+            left: 50%;
+        }
 
-            &:active {
-                background: #75c3ed;
-                border-color: #75c3ed;
-            }
+        .bkey4 {
+            left: 65%;
+        }
+
+        .bkey5 {
+            left: 80%;
         }
     }
 

+ 129 - 52
src/pc/component/keys/index.tsx

@@ -1,5 +1,6 @@
-import { defineComponent, onMounted, onUnmounted, reactive } from "vue";
+import { computed, defineComponent, onMounted, onUnmounted, reactive } from "vue";
 import styles from "./index.module.less";
+import { notationInstruments } from "../../create/component/the-create";
 
 export default defineComponent({
 	name: "Keys",
@@ -9,6 +10,10 @@ export default defineComponent({
 			type: Boolean,
 			default: false,
 		},
+		instrumentCode: {
+			type: String,
+			default: "",
+		},
 	},
 	setup(props, { emit }) {
 		const data = reactive({
@@ -22,6 +27,11 @@ export default defineComponent({
 				{ key: "B", singname: "si", type: "white" },
 			],
 			keyDown: "",
+			list: [] as any[],
+			range: {
+				min: 0,
+				max: 83,
+			},
 		});
 		/** 赤橙黄露青蓝紫 */
 		const colors = ["#F07C83", "#FF966C", "#FBB957", "#A7DCBF", "#CCCCD6", "#A5D2FF", "#B0A4F4"];
@@ -35,7 +45,61 @@ export default defineComponent({
 		const keyUp = (e: KeyboardEvent) => {
 			data.keyDown = "";
 		};
+		const initKeys = () => {
+			let noteIndex = 0;
+			const list: any[] = [];
+			for (let i = 0; i < 7; i++) {
+				const items: any = [];
+				for (let j = 0; j < data.keys.length; j++) {
+					const item = data.keys[j];
+					let key = i > 3 ? item.key.toLocaleLowerCase() : item.key;
+					const total = i > 3 ? ([3, 4].includes(i) ? 0 : i - 4) : i - 3;
+					items.push({
+						noteIndex,
+						index: i,
+						singname: item.singname,
+						key: item.key,
+						name: item.key + (i + 1),
+						type: "white",
+						value: key + productKey(total),
+					});
+					noteIndex++;
+					if (item.key !== "E" && item.key !== "B") {
+						items.push({
+							noteIndex,
+							bekey: "bkey" + j,
+							index: i,
+							key: item.key,
+							singname: item.singname,
+							name: "#" + item.key + (i + 1),
+							type: "black",
+							value: key + productKey(total) + "-" + "^",
+						});
+						noteIndex++;
+					}
+				}
+				list.push(items);
+			}
+			data.list = list;
+			// console.log(data.list);
+			// console.log(props.instrumentCode);
+			const range = notationInstruments.find((item) => item.key === props.instrumentCode)?.range;
+			if (range) {
+				data.range = range;
+			}
+		};
+		const noteList = computed(() => {
+			const list = data.list
+				.map((items) => {
+					return items.filter(
+						(item: any) => item.noteIndex >= data.range.min && item.noteIndex <= data.range.max
+					);
+				})
+				.filter((item) => item.length > 0);
+			return list;
+		});
 		onMounted(() => {
+			initKeys();
 			document.addEventListener("keydown", keyDown);
 			document.addEventListener("keyup", keyUp);
 		});
@@ -45,57 +109,70 @@ export default defineComponent({
 		});
 		return () => (
 			<div class={[styles.piano, props.show && styles.show]}>
-				{new Array(7).fill(0).map((_, index) => (
-					<div class={styles.pianoItemWrap}>
-						{data.keys.map((item) => {
-							return (
-								<div
-									class={[styles.item, index === 3 && data.keyDown === item.key && styles.keyDown]}
-									key={index}
-									onClick={() => {
-										let key = index > 3 ? item.key.toLocaleLowerCase() : item.key;
-										emit("click", {
-											type: "note",
-											value: key + productKey([3, 4].includes(index) ? 0 : index - 3),
-										});
-									}}
-								>
-									<div class={styles.keytip}>
-										<div style={{ color: "#ff4a00" }}>
-											{index === 3 && item.key === "C" ? "中央C" : ""}
-										</div>
-										<div class={styles.keyname}>
-											{item.key}
-											{index + 1}
-										</div>
-										<div class={styles.singname} style={{ background: colors[index] }}>
-											{item.singname}
-										</div>
-									</div>
-								</div>
-							);
-						})}
-						<div class={styles.bkeyWrap}>
-							{data.keys.map((item) => {
-								if (item.key === "E" || item.key === "B") return null;
-								return (
-									<div
-										class={styles.bkey}
-										onClick={() => {
-											let key = index > 3 ? item.key.toLocaleLowerCase() : item.key;
-											emit("click", {
-												type: "note",
-												value: key + productKey([3, 4].includes(index) ? 0 : index - 3) + "-" + "^",
-											});
-										}}
-									>
-										<div class="keytip"></div>
-									</div>
-								);
-							})}
-						</div>
-					</div>
-				))}
+				<div class={styles.pianoItemWrap}>
+					{noteList.value.map((items: any, index: number) => {
+						return (
+							<div class={styles.itemWrap} style={{ width: `calc(100% / ${noteList.value.length})` }}>
+								{items.map((item: any) => {
+									return (
+										<>
+											{item.type === "white" ? (
+												<div
+													style={{
+														display:
+															item.noteIndex < data.range.min || item.noteIndex > data.range.max
+																? "none"
+																: "",
+													}}
+													class={[
+														styles.item,
+														item.index === 3 && data.keyDown === item.key && styles.keyDown,
+													]}
+													key={item.index}
+													onClick={() => {
+														console.log(item.value);
+														emit("click", {
+															type: "note",
+															value: item.value,
+														});
+													}}
+												>
+													<div class={styles.keytip}>
+														<div style={{ color: "#ff4a00" }}>
+															{item.index === 3 && item.key === "C" ? "中央C" : ""}
+														</div>
+														<div class={styles.keyname}>{item.name}</div>
+														<div class={styles.singname} style={{ background: colors[item.index] }}>
+															{item.singname}
+														</div>
+													</div>
+												</div>
+											) : (
+												<div
+													style={{
+														display:
+															item.noteIndex < data.range.min || item.noteIndex > data.range.max
+																? "none"
+																: "",
+													}}
+													class={[styles.bkey, `${item.bekey}`]}
+													onClick={() => {
+														emit("click", {
+															type: "note",
+															value: item.value,
+														});
+													}}
+												>
+													<div class="keytip"></div>
+												</div>
+											)}
+										</>
+									);
+								})}
+							</div>
+						);
+					})}
+				</div>
 			</div>
 		);
 	},

+ 58 - 36
src/pc/create/component/the-create/index.tsx

@@ -29,6 +29,59 @@ import TheIcon from "/src/components/The-icon";
 import TheSpeed from "/src/pc/home/component/the-speed";
 import { api_musicSheetCreationSave, api_subjectList } from "/src/pc/api";
 import { initMusic } from "/src/pc/home";
+const instruments = [
+	{
+		label: "竖笛",
+		key: "recorder",
+		id: 4,
+		icon: getImage("icon_27_0.png"),
+		range:{
+			min: 48,
+			max: 74
+		}
+	},
+	{
+		label: "排箫",
+		key: "pan_flute",
+		id: 1,
+		icon: getImage("icon_27_1.png"),
+		range:{
+			min: 43,
+			max: 77
+		}
+	},
+	{
+		label: "口风琴",
+		key: "piccolo",
+		id: 5,
+		icon: getImage("icon_27_2.png"),
+		range:{
+			min: 41,
+			max: 72
+		}
+	},
+	{
+		label: "陶笛",
+		key: "blown_bottle",
+		id: 2,
+		icon: getImage("icon_27_3.png"),
+		range:{
+			min: 45,
+			max: 65
+		}
+	},
+	{
+		label: "葫芦丝",
+		key: "clarinet",
+		id: 3,
+		icon: getImage("icon_27_4.png"),
+		range:{
+			min: 40,
+			max: 57
+		}
+	},
+];
+export const notationInstruments = instruments;
 export default defineComponent({
 	name: "TheCreate",
 	props: {
@@ -40,38 +93,7 @@ export default defineComponent({
 	emits: ["update:show", "create"],
 	setup(props, { emit }) {
 		const message = useMessage();
-		const instruments = [
-			{
-				label: "竖笛",
-				key: "recorder",
-				id: 4,
-				icon: getImage("icon_27_0.png"),
-			},
-			{
-				label: "排箫",
-				key: "pan_flute",
-				id: 1,
-				icon: getImage("icon_27_1.png"),
-			},
-			{
-				label: "口风琴",
-				key: "piccolo",
-				id: 5,
-				icon: getImage("icon_27_2.png"),
-			},
-			{
-				label: "陶笛",
-				key: "blown_bottle",
-				id: 2,
-				icon: getImage("icon_27_3.png"),
-			},
-			{
-				label: "葫芦丝",
-				key: "clarinet",
-				id: 3,
-				icon: getImage("icon_27_4.png"),
-			},
-		];
+
 		const formsOptions = reactive({
 			subjects: [] as any[],
 			loading: false,
@@ -82,7 +104,7 @@ export default defineComponent({
 			meter: ABC_DATA.meter[0],
 			speed: 80,
 			measure: 30,
-			subjectCode: "recorder"
+			subjectCode: "recorder",
 		});
 
 		const handleCreate = async () => {
@@ -151,15 +173,15 @@ export default defineComponent({
 								<div
 									class={[styles.item, froms.subjectId === item.id && styles.itemActive]}
 									onClick={() => {
-										froms.subjectId = item.id
-										froms.subjectCode = item.key
+										froms.subjectId = item.id;
+										froms.subjectCode = item.key;
 									}}
 								>
 									<div class={styles.itemImg}>
 										<img class={styles.icon} src={item.icon} />
 									</div>
 									<div>{item.label}</div>
-									<img class={styles.itemIcon} src={getImage('icon_check.png')} />
+									<img class={styles.itemIcon} src={getImage("icon_check.png")} />
 								</div>
 							))}
 						</NSpace>

+ 8 - 3
src/pc/home/index.tsx

@@ -162,6 +162,7 @@ export default defineComponent({
       selectMearesShow: false, // 选择小节弹窗
     });
     const data = reactive({
+		loading: true,
       drawCount: 0,
       isSave: false,
       musicId: "",
@@ -332,7 +333,9 @@ export default defineComponent({
         cursor.setAttributeNS(null, "y2", "0");
         svg?.appendChild(cursor);
       },
-      onBeat: function (beatNumber: any, totalBeats: any, totalTime: any) {},
+      onBeat: function (beatNumber: any, totalBeats: any, totalTime: any) {
+		// console.log("🚀 ~ beatNumber:", beatNumber, totalBeats, totalTime, abcData.visualObj.getBeatLength());
+	  },
       onEvent: (ev: any) => {
         // console.log("🚀 ~ ev:", ev);
         if (!data.playState) return;
@@ -1068,6 +1071,7 @@ export default defineComponent({
       }));
     });
     const getDetailData = async () => {
+		data.loading = true;
       const query: any = getQuery();
       const res = await api_musicSheetCreationDetail(query.id);
       if (res?.code == 200) {
@@ -1095,6 +1099,7 @@ export default defineComponent({
           // console.log("🚀 ~ abcData.abc:", abcData.abc);
         }
       }
+	  data.loading = false
     };
     const handleSaveMusic = async (tips = true) => {
       await api_musicSheetCreationUpdate({
@@ -1901,10 +1906,10 @@ export default defineComponent({
               </div>
             </div>
             <div id="paper"></div>
-            <Keys show={data.active ? true : false} onClick={(val) => handleChange(val)} />
+            { !data.loading && <Keys show={data.active ? true : false} instrumentCode={abcData.abc.subjectCode} onClick={(val) => handleChange(val)} />}
 
             {/* <textarea ref={textAreaRef} class={styles.value} id="abc"></textarea> */}
-            <div id="audio" style={{ opacity: 0 }}></div>
+            <div id="audio" style={{ display: 'none' }}></div>
             <div id="warnings"></div>
 
             <p class="beat"></p>