|
@@ -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,7 +167,16 @@ export const filterMoveData = async () => {
|
|
|
const list = moveData.modelList
|
|
|
.filter((n) => n.isMove)
|
|
|
.map((n) => {
|
|
|
- const item: any = {
|
|
|
+ /**
|
|
|
+ * 找到移动后,此时与此元素距离最近的音符,并记录音符的索引和此元素与音符的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;
|
|
|
+ let item: any = {
|
|
|
id: n.id,
|
|
|
isMove: n.isMove,
|
|
|
isDelete: n.isDelete,
|
|
@@ -143,10 +187,18 @@ 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;
|
|
|
}
|
|
|
+ if (n.id.includes('text')) {
|
|
|
+ // let copyDom = document.querySelector("#" + n.id)!.cloneNode(true) as SVGSVGElement
|
|
|
+ const textContent = document.querySelector("#" + n.id)?.querySelector("text")?.innerHTML || ''
|
|
|
+ item.textContent = textContent
|
|
|
+ }
|
|
|
return item;
|
|
|
});
|
|
|
// if (!list.length) {
|
|
@@ -176,6 +228,7 @@ const dragData = {
|
|
|
startY: 0,
|
|
|
x: 0,
|
|
|
y: 0,
|
|
|
+ repeatEdit: false,
|
|
|
};
|
|
|
|
|
|
// 记录
|
|
@@ -195,6 +248,7 @@ function onDown(e: MouseEvent) {
|
|
|
dragData.startY = e.clientY;
|
|
|
dragData.x = item.x;
|
|
|
dragData.y = item.y;
|
|
|
+ dragData.repeatEdit = item.noteIdx >= 0 ? true : false;
|
|
|
// console.log("🚀 ~ 按下", index, el, item.x, item.y);
|
|
|
document.onmousemove = onMove;
|
|
|
document.onmouseup = onUp;
|
|
@@ -213,7 +267,7 @@ function onMove(e: MouseEvent) {
|
|
|
if (dragData.open) {
|
|
|
const _x = e.clientX - dragData.startX + dragData.x;
|
|
|
const _y = e.clientY - dragData.startY + dragData.y;
|
|
|
- setModelPostion(moveData.modelList[moveData.activeIndex], _x, _y);
|
|
|
+ setModelPostion(moveData.modelList[moveData.activeIndex], _x, _y, dragData.repeatEdit);
|
|
|
}
|
|
|
}
|
|
|
function onUp(e: MouseEvent) {
|
|
@@ -247,23 +301,37 @@ const renderSvgItem = (item: any) => {
|
|
|
};
|
|
|
|
|
|
/** 设置元素位置 */
|
|
|
-function setModelPostion(item: any, x: number, y: number) {
|
|
|
+async function setModelPostion(item: any, x: number, y: number, repeatEdit?: boolean) {
|
|
|
// console.log(item)
|
|
|
+ //console.log('位置',x,y)
|
|
|
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 = "");
|
|
|
} else {
|
|
|
/** 如果是app内嵌打开,需要通过rem转换 */
|
|
|
let tsX = x, tsY = y;
|
|
|
- if (storeData.isApp && (item.xRem || item.yRem)) {
|
|
|
- tsX = item.xRem * clientWidth/10
|
|
|
- tsY = item.yRem * clientWidth/10
|
|
|
+ // if (storeData.isApp && (item.xRem || item.yRem)) {
|
|
|
+ // tsX = item.xRem * clientWidth/10
|
|
|
+ // tsY = item.yRem * clientWidth/10
|
|
|
+ // }
|
|
|
+ if (item.noteIdx >= 0 && !repeatEdit) {
|
|
|
+ if (!moveData.noteCoords.length) {
|
|
|
+ await initNoteCoord()
|
|
|
+ }
|
|
|
+ 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)`);
|
|
|
}
|
|
|
- g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
|
|
|
- el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -412,7 +480,25 @@ export const renderForMoveData = () => {
|
|
|
nextTick(() => {
|
|
|
console.log("🚀 ~ list", list);
|
|
|
list.forEach((item: any) => {
|
|
|
- const index = moveData.modelList.findIndex((n: any) => n.id === item.id);
|
|
|
+ let index = moveData.modelList.findIndex((n: any) => n.id === item.id);
|
|
|
+ if (item.type === 'vf-text' && item.textContent) {
|
|
|
+ let textValue = document.querySelector("#" + moveData.modelList[index].id)?.querySelector("text")?.innerHTML || ''
|
|
|
+ let targetIndex = index, preEnd = false;
|
|
|
+ while (textValue !== item.textContent) {
|
|
|
+ if (preEnd) {
|
|
|
+ targetIndex = targetIndex + 1
|
|
|
+ } else {
|
|
|
+ targetIndex = targetIndex > 0 ? targetIndex - 1 : targetIndex
|
|
|
+ }
|
|
|
+ if (targetIndex == 0) preEnd = true
|
|
|
+ textValue = document.querySelector("#" + moveData.modelList[targetIndex].id)?.querySelector("text")?.innerHTML || ''
|
|
|
+ }
|
|
|
+ // index = targetIndex + 1
|
|
|
+ // item.id = `text${index}`
|
|
|
+ index = targetIndex
|
|
|
+ item.id = `text${targetIndex+1}`
|
|
|
+ }
|
|
|
+ console.log(66666666,index)
|
|
|
if (index > -1) {
|
|
|
moveData.modelList[index] = {
|
|
|
...moveData.modelList[index],
|
|
@@ -439,6 +525,7 @@ export default defineComponent({
|
|
|
// initSvgId();
|
|
|
// }
|
|
|
// renderForMoveData();
|
|
|
+ nextTick(() => initNoteCoord())
|
|
|
const toolBox = document.getElementById("toolBox");
|
|
|
toolBox && document.body.appendChild(toolBox);
|
|
|
});
|