Browse Source

分割音符,和添加音符时值过长

liushengqiang 1 year ago
parent
commit
6297cd9e71
3 changed files with 56 additions and 37 deletions
  1. 47 32
      src/pc/home/index.tsx
  2. 7 5
      src/pc/home/runtime.ts
  3. 2 0
      src/pc/types.ts

+ 47 - 32
src/pc/home/index.tsx

@@ -140,6 +140,7 @@ export const initMusic = (total: number): IMeasure[] => {
 					dot: "",
 					slus: "",
 					tieline: "",
+					segno: "",
 				},
 			],
 		};
@@ -515,6 +516,23 @@ export default defineComponent({
 			return abcElem;
 		};
 
+		const useIndexGetNote = (indexStr: string) => {
+			const index = data.music.indexOf(indexStr);
+			const note = abcData.visualObj.getElementFromChar(index);
+			return note;
+		};
+
+		const getMeasureNotes = (measureIndex: number) => {
+			const measure = abcData.abc.measures[measureIndex];
+			const notes = [];
+			for (let k = 0; k < measure.notes.length; k++) {
+				const indexStr = `${measureIndex}.${k}`;
+				const note = useIndexGetNote(indexStr);
+				notes.push(note);
+			}
+			return notes;
+		};
+
 		/**
 		 *
 		 * @param key
@@ -547,15 +565,24 @@ export default defineComponent({
 				return;
 			}
 
+			// 分割
+			if (type === "segno") {
+				if (!data.active) {
+					showToast("请先选择音符");
+					return;
+				}
+				if (!activeNote) return;
+				activeNote.segno = activeNote.segno ? "" : value;
+				await handleResetRender();
+				rangeHighlight(data.active.startChar);
+			}
+
 			// 修改音符,或者添加音符
 			if (type === "note") {
-				if (data.active) {
-					if (data.active.el_type !== "note") return;
+				if (data.active && data.active.el_type == "note") {
 					const activeNote =
 						abcData.abc.measures[data.active.measureIndex]?.notes[data.active.noteIndex] || null;
-					// console.log(activeNote, data.active.isFirstChecked);
 					const _values = value.split("-");
-					// console.log("🚀 ~ _value:", _values);
 					if (data.active.isFirstChecked) {
 						activeNote.content = _values[0];
 						activeNote.noteType = data.noteType;
@@ -563,6 +590,12 @@ export default defineComponent({
 							activeNote.accidental = _values[1] || "";
 						}
 					} else {
+						const notes = getMeasureNotes(data.active.measureIndex);
+						const duration = notes.map((n) => n.duration).reduce((a, b) => a + b);
+						if (duration >= 1) {
+							message.warning("小节内音符总时值过长");
+							return;
+						}
 						handleCreateNote(
 							data.active.measureIndex,
 							data.active.noteIndex,
@@ -595,18 +628,6 @@ export default defineComponent({
 					}
 					if (!_abcElem?.midiPitches) return;
 					ABCJS.synth.playEvent(_abcElem.midiPitches, _abcElem.midiGraceNotePitches, 1000);
-				} else {
-					const measureIndex = abcData.abc.measures.length - 1;
-					const noteIndex = abcData.abc.measures[measureIndex].notes.length - 1;
-					handleCreateNote(
-						measureIndex,
-						noteIndex,
-						createNote({
-							content: value,
-							noteType: data.noteType,
-						})
-					);
-					handleResetRender();
 				}
 			}
 
@@ -616,8 +637,6 @@ export default defineComponent({
 					showToast("请先选择音符");
 					return;
 				}
-				const activeNote =
-					abcData.abc.measures[data.active.measureIndex]?.notes[data.active.noteIndex] || null;
 				if (activeNote.content === "z") {
 					showToast("休止符无法添加临时升降记号");
 					return;
@@ -639,8 +658,6 @@ export default defineComponent({
 			// 谱号
 			if (type === "clef") {
 				if (data.active) {
-					const activeNote =
-						abcData.abc.measures[data.active.measureIndex]?.notes[data.active.noteIndex] || null;
 					if (!activeNote) return;
 					activeNote.clef = `[${value}]`;
 					await handleResetRender();
@@ -653,8 +670,6 @@ export default defineComponent({
 			// 调号
 			if (type === "key") {
 				if (data.active) {
-					const activeNote =
-						abcData.abc.measures[data.active.measureIndex]?.notes[data.active.noteIndex] || null;
 					if (!activeNote) return;
 					activeNote.key = `[${value}]`;
 					await handleResetRender();
@@ -667,8 +682,6 @@ export default defineComponent({
 			// 拍号
 			if (type === "meter") {
 				if (data.active) {
-					const activeNote =
-						abcData.abc.measures[data.active.measureIndex]?.notes[data.active.noteIndex] || null;
 					if (!activeNote) return;
 					activeNote.meter = `[${value}]`;
 					await handleResetRender();
@@ -684,8 +697,6 @@ export default defineComponent({
 					showToast("请先选择音符");
 					return;
 				}
-				const activeNote =
-					abcData.abc.measures[data.active.measureIndex]?.notes[data.active.noteIndex] || null;
 				if (!activeNote) return;
 				if (activeNote.play.includes(value)) {
 					activeNote.play = activeNote.play.filter((item) => item !== value);
@@ -701,8 +712,6 @@ export default defineComponent({
 					message.info("请先选择音符");
 					return;
 				}
-				const activeNote =
-					abcData.abc.measures[data.active?.measureIndex]?.notes[data.active?.noteIndex] || null;
 				if (!activeNote) return;
 				if (Array.isArray(value)) {
 					if (activeNote?.dynamics) {
@@ -741,8 +750,6 @@ export default defineComponent({
 					message.info("请先选择音符");
 					return;
 				}
-				const activeNote =
-					abcData.abc.measures[data.active?.measureIndex]?.notes[data.active?.noteIndex] || null;
 				if (!activeNote) return;
 				if (Array.isArray(value)) {
 					if (activeNote?.tie) {
@@ -1075,7 +1082,6 @@ export default defineComponent({
 			if (!data.active) return {} as unknown as INote;
 			const activeNote =
 				abcData.abc.measures[data.active.measureIndex]?.notes[data.active.noteIndex] || {};
-			console.log("🚀 ~ activeNote:", activeNote);
 			return activeNote;
 		});
 
@@ -1810,10 +1816,19 @@ export default defineComponent({
 										<div
 											class={[styles.btnImg, noteComputed.value.content === "z" && styles.btnImgActive]}
 										>
-											<img style={{ width: "24px", height: "24px" }} src={getImage("icon_rest.png")} />
+											<img style={{ width: "20px", height: "20px" }} src={getImage("icon_rest.png")} />
 										</div>
 										<div>休止符</div>
 									</div>
+
+									<div class={styles.topBtn} onClick={() => handleChange({ type: "segno", value: " " })}>
+										<div
+											class={[styles.btnImg, noteComputed.value.segno === " " && styles.btnImgActive]}
+										>
+											{/* <img style={{ width: "20px", height: "20px" }} src={getImage("icon_rest.png")} /> */}
+										</div>
+										<div>分割</div>
+									</div>
 								</div>
 							</CollapseItem>
 							<CollapseItem title="谱号" name="clef">

+ 7 - 5
src/pc/home/runtime.ts

@@ -7,11 +7,11 @@ export const ABC_DATA = {
 	/** 音符 */
 	types: [
 		{ name: "全音符", value: "4", icon: "icon-quanyinfu" },
-		{ name: "分音符", value: "2", icon: "icon-a-2fenyinfu" },
-		{ name: "分音符", value: "", icon: "icon-a-4fenyinfu" },
-		{ name: "分音符", value: "/", icon: "icon-a-8fenyinfu" },
-		{ name: "十六分音符", value: "//", icon: "icon-a-16fenyinfu" },
-		{ name: "三十二分音符", value: "///", icon: "icon-a-32fenyinfu" },
+		{ name: "2分音符", value: "2", icon: "icon-a-2fenyinfu" },
+		{ name: "4分音符", value: "", icon: "icon-a-4fenyinfu" },
+		{ name: "8分音符", value: "/", icon: "icon-a-8fenyinfu" },
+		{ name: "16分音符", value: "//", icon: "icon-a-16fenyinfu" },
+		{ name: "32音符", value: "///", icon: "icon-a-32fenyinfu" },
 	],
 	/** 休止符 */
 	reset: [{ name: "休止符", value: "z", icon: "icon-a-4fenxiuzhifu" }],
@@ -158,6 +158,7 @@ export const createNote = (options: Partial<INote>): INote => {
 		dot: options.dot || "",
 		slus: options.slus || "",
 		tieline: options.tieline || "",
+		segno: options.segno || "",
 	};
 };
 
@@ -218,6 +219,7 @@ export const renderMeasures = (abc: IAbc) => {
 				// 连音线 后
 				text += note.tie;
 			}
+			text += note.segno; // 分割
 		}
 		text += measure.barline;
 		// text += `"${i}"` + measure.barline;

+ 2 - 0
src/pc/types.ts

@@ -31,6 +31,8 @@ export interface INote {
 	slus: string
 	/** 延音 */
 	tieline: string
+	/** 分割 */
+	segno: string
 }
 export interface IMeasure {
 	/** 小节号 */