Forráskód Böngészése

feat: 谱面元素编辑1.2

TIANYONG 1 éve
szülő
commit
e40734822f

+ 62 - 4
src/view/plugins/move-music-score/index.tsx

@@ -28,8 +28,43 @@ export const moveData = reactive({
 	tool: {
 		isAddAndSub: false,
 	},
+	noteCoords: [] as any[],
 });
 
+// 所以可点击音符的dom坐标集合
+const initNoteCoord = () => {
+	const allNoteDot: any = Array.from(document.querySelectorAll('.node-dot'));
+ 	moveData.noteCoords = allNoteDot.map((note: any) => {
+		const note_bbox = note?.getBoundingClientRect?.() || { x: 0, y: 0 };
+		return {
+			x: note_bbox.x,
+			y: note_bbox.y
+		}
+	})
+}
+
+// 找出离目标元素最近的音符
+const computedDistance = (x: number, y: number) => {
+    let minDistance = -1, minidx = 0;
+    let a, b, c;
+	moveData.noteCoords.forEach((note: any, idx: any) => {
+		//a,b为直角三角形的两个直角边
+		a = Math.abs(note.x - x)
+		b = Math.abs(note.y - y)
+		//c为直角三角形的斜边
+		c = Math.sqrt(a * a + b * b) as 0
+		c = Number(c.toFixed(0)) as 0
+		if (c !== 0 && (minDistance === - 1 || c < minDistance)) {
+			//min为元素中离目标元素最近元素的距离
+			minDistance = c
+			minidx = idx
+		}		
+	})
+    return minidx
+}
+
+
+
 function initSvgId() {
 	const svg = document.querySelector("#osmdSvgPage1");
 	if (!svg) return;
@@ -132,6 +167,15 @@ export const filterMoveData = async () => {
 		const list = moveData.modelList
 			.filter((n) => n.isMove)
 			.map((n) => {
+				/**
+				 * 找到移动后,此时与此元素距离最近的音符,并记录音符的索引和此元素与音符的x轴,y轴的间距
+				*/
+				// 元素的位置
+				const elementX = n.left + n.x, elementY = n.top + n.y;
+				// 找出距离元素最近的音符
+				const noteIdx = computedDistance(elementX, elementY);
+				// 此元素距离最近音符的x轴,y轴距离
+				const noteRelativeX = elementX - moveData.noteCoords[noteIdx]?.x, noteRelativeY = elementY - moveData.noteCoords[noteIdx]?.y;
 				const item: any = {
 					id: n.id,
 					isMove: n.isMove,
@@ -143,6 +187,9 @@ export const filterMoveData = async () => {
 					zoom: n.zoom,
 					w: moveData.sw,
 					type: n.type,
+					noteIdx,
+					noteRelativeX,
+					noteRelativeY
 				};
 				if (n.type === "vf-lineGroup") {
 					item.dx = n.dx;
@@ -250,8 +297,8 @@ const renderSvgItem = (item: any) => {
 function setModelPostion(item: any, x: number, y: number) {
 	// console.log(item)
 	if (item) {
-		const g = document.querySelector("#" + item.id)!;
-		const el: HTMLElement = document.querySelector(`[data-id=${item.id}]`)!;
+		const g = document.querySelector("#" + item.id)!; // svg元素
+		const el: HTMLElement = document.querySelector(`[data-id=${item.id}]`)!; // svg元素的背景div
 		if (x === 0 && y === 0) {
 			g && g.removeAttribute("transform");
 			el && (el.style.transform = "");
@@ -262,8 +309,18 @@ function setModelPostion(item: any, x: number, y: number) {
 			// 	tsX = item.xRem * clientWidth/10
 			// 	tsY = item.yRem * clientWidth/10
 			// }
-			g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
-			el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
+			if (item.noteIdx >= 0) {
+				const targetX = moveData.noteCoords[item.noteIdx].x + item.noteRelativeX, targetY = moveData.noteCoords[item.noteIdx].y + item.noteRelativeY;
+				const original = document.getElementById(item.id)?.getBoundingClientRect() || { x: 0, y: 0 };
+				tsX = targetX - original.x;
+				tsY = targetY - original.y;
+				console.log('距离',tsX,tsY,x,y)
+				g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
+				el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
+			} else {
+				g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
+				el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
+			}
 		}
 	}
 }
@@ -439,6 +496,7 @@ export default defineComponent({
 			// 	initSvgId();
 			// }
 			// renderForMoveData();
+			nextTick(() => initNoteCoord())
 			const toolBox = document.getElementById("toolBox");
 			toolBox && document.body.appendChild(toolBox);
 		});

+ 11 - 0
src/view/selection/index.module.less

@@ -13,6 +13,7 @@
 
 .note {
     cursor: pointer;
+    // background: rgba(0,0,0,0.3);
 }
 
 
@@ -243,4 +244,14 @@
         min-height: 94Px;
         transform: translateX(8.5Px,-50%);
     } 
+}
+
+.noteDot {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%);
+    width: 2px;
+    height: 2px;
+    // background: #07c160;
 }

+ 1 - 0
src/view/selection/index.tsx

@@ -299,6 +299,7 @@ export default defineComponent({
 								<Icon name="success" />
 								<Icon name="cross" />
 							</div>
+							<div class={[styles.noteDot, 'node-dot']}></div>
 						</div>
 					);
 				})}

+ 2 - 2
vite.config.ts

@@ -68,8 +68,8 @@ export default defineConfig({
 				// target: "https://test.lexiaoya.cn",
 				// target: "https://dev.kt.colexiu.com",
 				// target: "https://test.resource.colexiu.com", // 内容平台开发环境,内容平台开发,需在url链接上加上isCbs=true
-				// target: "https://test.resource.colexiu.com",
-				target: "https://test.kt.colexiu.com",
+				target: "https://test.resource.colexiu.com",
+				// target: "https://test.kt.colexiu.com",
 				changeOrigin: true,
 				rewrite: (path) => path.replace(/^\/instrument/, ""),
 			},