|
@@ -1,12 +1,19 @@
|
|
|
-import { showToast } from "vant";
|
|
|
+import { Row, showToast } from "vant";
|
|
|
import { defineComponent, onMounted, reactive } from "vue";
|
|
|
import state from "/src/state";
|
|
|
-import { detailData_gym } from "../../../page-gym/detail";
|
|
|
import request from "/src/utils/request";
|
|
|
import { getQuery } from "/src/utils/queryString";
|
|
|
+import styles from "./index.module.less";
|
|
|
+import { Button, ButtonGroup, Icon, Switch, Tooltip } from "@varlet/ui";
|
|
|
+import "@varlet/ui/es/tooltip/style";
|
|
|
+import "@varlet/ui/es/button-group/style";
|
|
|
+import "@varlet/ui/es/switch/style";
|
|
|
|
|
|
let extStyleConfigJson: any = {};
|
|
|
export const moveData = reactive({
|
|
|
+ /** 开启移动 */
|
|
|
+ open: false,
|
|
|
+ zoom: state.zoom,
|
|
|
partIndex: "0",
|
|
|
hasExtJson: false,
|
|
|
isWeb: false,
|
|
@@ -20,12 +27,10 @@ export const moveData = reactive({
|
|
|
|
|
|
function initSvgId() {
|
|
|
const svg = document.querySelector("#osmdSvgPage1");
|
|
|
- console.log("🚀 ~ svg:", svg);
|
|
|
if (!svg) return;
|
|
|
const vfstavetempo: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-stavetempo"));
|
|
|
const vftext: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-text"));
|
|
|
- console.log("🚀 ~ vftext:", vftext);
|
|
|
- const vfstaveSection: HTMLElement[] = []//Array.from(svg.querySelectorAll(".vf-StaveSection"));
|
|
|
+ const vfstaveSection: HTMLElement[] = []; //Array.from(svg.querySelectorAll(".vf-StaveSection"));
|
|
|
const vfRepetition: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-Repetition"));
|
|
|
const vflineGroup: HTMLElement[] = Array.from(svg.querySelectorAll(".vf-lineGroup"));
|
|
|
let tempIndex = 1;
|
|
@@ -70,51 +75,15 @@ function setEleId(ele: HTMLElement, eleId: string) {
|
|
|
createModelBox(ele as any);
|
|
|
}
|
|
|
|
|
|
-const reloadReader = () => {
|
|
|
- const detail = detailData_gym;
|
|
|
- if (detail.extStyleConfigJson) {
|
|
|
- try {
|
|
|
- extStyleConfigJson = JSON.parse(detail.extStyleConfigJson);
|
|
|
- } catch (error) {
|
|
|
- extStyleConfigJson = {};
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!extStyleConfigJson || !extStyleConfigJson?.[moveData.partIndex]) return;
|
|
|
- const list = extStyleConfigJson?.[moveData.partIndex];
|
|
|
- if (list && Array.isArray(list)) {
|
|
|
- console.log("🚀 ~ list", list);
|
|
|
- list.forEach((item: any) => {
|
|
|
- const index = moveData.modelList.findIndex((n: any) => n.id === item.id);
|
|
|
- if (index > -1) {
|
|
|
- item.x = moveData.sw && item.w ? item.x * (moveData.sw / item.w) : item.x;
|
|
|
- moveData.modelList[index] = {
|
|
|
- ...moveData.modelList[index],
|
|
|
- ...item,
|
|
|
- };
|
|
|
- setModelPostion(moveData.modelList[index]);
|
|
|
- if (item.type === "vf-lineGroup") {
|
|
|
- renderLineGroup(moveData.modelList[index]);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-};
|
|
|
-const zoom = 0.7;
|
|
|
-
|
|
|
-function formateZoom(n: number) {
|
|
|
- return n * zoom;
|
|
|
-}
|
|
|
-
|
|
|
function createModelBox(ele: SVGAElement) {
|
|
|
const musicContainer = document.getElementById("musicAndSelection")?.getBoundingClientRect() || { x: 0, y: 0 };
|
|
|
const parentLeft = musicContainer.x || 0;
|
|
|
const parentTop = musicContainer.y || 0;
|
|
|
const noteBbox = ele.getBoundingClientRect();
|
|
|
const bbox = {
|
|
|
- left: noteBbox.x - parentLeft - noteBbox.width / 4 + "px",
|
|
|
+ left: noteBbox.x - parentLeft + "px",
|
|
|
top: noteBbox.y - parentTop + "px",
|
|
|
- width: noteBbox.width * 1.5 + "px",
|
|
|
+ width: noteBbox.width + "px",
|
|
|
height: noteBbox.height + "px",
|
|
|
};
|
|
|
const type = ele.getAttribute("class");
|
|
@@ -129,7 +98,7 @@ function createModelBox(ele: SVGAElement) {
|
|
|
height: noteBbox.height,
|
|
|
x: 0,
|
|
|
y: 0,
|
|
|
- zoom,
|
|
|
+ zoom: state.zoom,
|
|
|
isDelete: false,
|
|
|
d2: getLineGroupPathDx(ele as any),
|
|
|
dx: 0,
|
|
@@ -138,12 +107,15 @@ function createModelBox(ele: SVGAElement) {
|
|
|
|
|
|
function getBox(ele: SVGAElement) {
|
|
|
if (!ele) return {};
|
|
|
- const box = ele.getBBox();
|
|
|
+ const musicContainer = document.getElementById("musicAndSelection")?.getBoundingClientRect() || { x: 0, y: 0 };
|
|
|
+ const parentLeft = musicContainer.x || 0;
|
|
|
+ const parentTop = musicContainer.y || 0;
|
|
|
+ const box = ele.getBoundingClientRect();
|
|
|
return {
|
|
|
- left: formateZoom(box.x - 5),
|
|
|
- top: formateZoom(box.y - 5),
|
|
|
- width: formateZoom(box.width + 10),
|
|
|
- height: formateZoom(box.height + 10),
|
|
|
+ left: box.x - parentLeft,
|
|
|
+ top: box.y - parentTop,
|
|
|
+ width: box.width,
|
|
|
+ height: box.height,
|
|
|
};
|
|
|
}
|
|
|
|
|
@@ -169,27 +141,32 @@ export const filterMoveData = async () => {
|
|
|
}
|
|
|
return item;
|
|
|
});
|
|
|
- extStyleConfigJson[moveData.partIndex] = list;
|
|
|
- // console.log("🚀 ~ extStyleConfigJson", extStyleConfigJson)
|
|
|
- const res = await request.post("/sysMusicScore/updateExtStyleConfigJson", {
|
|
|
- data: {
|
|
|
- sysMusicScoreId: examSongId,
|
|
|
- extStyleConfigJson: JSON.stringify(extStyleConfigJson),
|
|
|
- },
|
|
|
- });
|
|
|
- // console.log(res)
|
|
|
- if (res && res.code == 200) {
|
|
|
- showToast("保存成功");
|
|
|
+ if (!list.length) {
|
|
|
+ showToast("请移动元素后再保存");
|
|
|
+ return
|
|
|
}
|
|
|
- clearActiveModel();
|
|
|
+ extStyleConfigJson[moveData.partIndex] = list;
|
|
|
+ console.log("🚀 ~ extStyleConfigJson", extStyleConfigJson)
|
|
|
+ // const res = await request.post("/sysMusicScore/updateExtStyleConfigJson", {
|
|
|
+ // data: {
|
|
|
+ // sysMusicScoreId: examSongId,
|
|
|
+ // extStyleConfigJson: JSON.stringify(extStyleConfigJson),
|
|
|
+ // },
|
|
|
+ // });
|
|
|
+ // if (res && res.code == 200) {
|
|
|
+ // showToast("保存成功");
|
|
|
+ // }
|
|
|
+ // clearActiveModel();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 移动
|
|
|
const dragData = {
|
|
|
- moving: false,
|
|
|
+ open: false,
|
|
|
startX: 0,
|
|
|
startY: 0,
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
};
|
|
|
|
|
|
// 记录
|
|
@@ -199,114 +176,105 @@ export const undoData = reactive({
|
|
|
activeItem: null,
|
|
|
});
|
|
|
|
|
|
-function dragmove(div: HTMLElement) {
|
|
|
- div.addEventListener("mousedown", onDown);
|
|
|
-}
|
|
|
-
|
|
|
function onDown(e: MouseEvent) {
|
|
|
- if (dragData.moving) return;
|
|
|
const el: any = e.target;
|
|
|
const index = moveData.modelList.findIndex((n) => n.id === el.dataset.id);
|
|
|
if (index > -1) {
|
|
|
- // console.log("🚀 ~ 按下", index, el);
|
|
|
const item = moveData.modelList[index];
|
|
|
moveData.activeIndex = index;
|
|
|
- e.stopPropagation();
|
|
|
- e.preventDefault();
|
|
|
- dragData.startX = e.clientX - item.x;
|
|
|
- dragData.startY = e.clientY - item.y;
|
|
|
- document.addEventListener("mousemove", onMove);
|
|
|
- document.addEventListener("mouseup", onUp);
|
|
|
- dragData.moving = true;
|
|
|
+ dragData.startX = e.clientX;
|
|
|
+ dragData.startY = e.clientY;
|
|
|
+ dragData.x = item.x;
|
|
|
+ dragData.y = item.y;
|
|
|
+ // console.log("🚀 ~ 按下", index, el, item.x, item.y);
|
|
|
+ document.onmousemove = onMove;
|
|
|
+ document.onmouseup = onUp;
|
|
|
+ dragData.open = true;
|
|
|
if (item.type === "vf-lineGroup") {
|
|
|
moveData.tool.isAddAndSub = true;
|
|
|
} else {
|
|
|
moveData.tool.isAddAndSub = false;
|
|
|
}
|
|
|
undoData.activeItem = { ...item };
|
|
|
+ return;
|
|
|
}
|
|
|
- setActiveModel(el);
|
|
|
+ moveData.activeIndex = -1;
|
|
|
}
|
|
|
function onMove(e: MouseEvent) {
|
|
|
- if (dragData.moving) {
|
|
|
- const _x = e.clientX - dragData.startX;
|
|
|
- const _y = e.clientY - dragData.startY;
|
|
|
- moveData.modelList[moveData.activeIndex].isMove = true;
|
|
|
- moveData.modelList[moveData.activeIndex].x = _x;
|
|
|
- moveData.modelList[moveData.activeIndex].y = _y;
|
|
|
- const item = moveData.modelList[moveData.activeIndex];
|
|
|
- setModelPostion(item);
|
|
|
+ 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);
|
|
|
}
|
|
|
}
|
|
|
-function onUp() {
|
|
|
+function onUp(e: MouseEvent) {
|
|
|
// console.log("🚀 ~ 抬起");
|
|
|
- document.removeEventListener("mousemove", onMove);
|
|
|
- document.removeEventListener("mouseup", onUp);
|
|
|
- dragData.moving = false;
|
|
|
- if (undoData.activeItem) {
|
|
|
- undoData.undoList.push({ ...(undoData.activeItem as any) });
|
|
|
+ document.onmousemove = null;
|
|
|
+ document.onmouseup = null;
|
|
|
+ dragData.open = false;
|
|
|
+ const _x = e.clientX - dragData.startX + dragData.x;
|
|
|
+ const _y = e.clientY - dragData.startY + dragData.y;
|
|
|
+ if (_x || _y) {
|
|
|
+ moveData.modelList[moveData.activeIndex].isMove = true;
|
|
|
+ moveData.modelList[moveData.activeIndex].x = _x;
|
|
|
+ moveData.modelList[moveData.activeIndex].y = _y;
|
|
|
+ if (undoData.activeItem) {
|
|
|
+ undoData.undoList.push({ ...(undoData.activeItem as any) });
|
|
|
+ }
|
|
|
}
|
|
|
undoData.activeItem = null;
|
|
|
}
|
|
|
|
|
|
-function setModelPostion(item: any) {
|
|
|
+/** 渲染svg元素的属性 */
|
|
|
+const renderSvgItem = (item: any) => {
|
|
|
+ setModelPostion(item, item.x, item.y);
|
|
|
+ if (item.isDelete) {
|
|
|
+ const g = document.querySelector("#" + item.id)!;
|
|
|
+ g && ((g as any).style.display = "none");
|
|
|
+ } else {
|
|
|
+ const g = document.querySelector("#" + item.id)!;
|
|
|
+ g && ((g as any).style.display = "");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/** 设置元素位置 */
|
|
|
+function setModelPostion(item: any, x: number, y: number) {
|
|
|
if (item) {
|
|
|
const g = document.querySelector("#" + item.id)!;
|
|
|
- g && g.setAttribute("transform", `translate(${item.x / zoom}, ${item.y / zoom})`);
|
|
|
const el: HTMLElement = document.querySelector(`[data-id=${item.id}]`)!;
|
|
|
- if (el) {
|
|
|
- el.style.left = item.left + item.x + "px";
|
|
|
- el.style.top = item.top + item.y + "px";
|
|
|
- el.style.width = item.width + "px";
|
|
|
- el.style.height = item.height + "px";
|
|
|
- }
|
|
|
- if (item.isDelete) {
|
|
|
- g && ((g as any).style.display = "none");
|
|
|
- el && ((el as any).style.display = "none");
|
|
|
+ if (x === 0 && y === 0) {
|
|
|
+ g && g.removeAttribute("transform");
|
|
|
+ el && (el.style.transform = "");
|
|
|
} else {
|
|
|
- g && ((g as any).style.display = "");
|
|
|
- el && ((el as any).style.display = "");
|
|
|
+ g && g.setAttribute("transform", `translate(${x / moveData.zoom}, ${y / moveData.zoom})`);
|
|
|
+ el && (el.style.transform = `translate(${x}px, ${y}px)`);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function setActiveModel(_div: HTMLElement) {
|
|
|
- if (!_div) return;
|
|
|
- moveData.modelList.forEach((n) => {
|
|
|
- const el: HTMLElement = document.querySelector(`[data-id=${n.id}]`)!;
|
|
|
- if (el) {
|
|
|
- if (n.id == _div.dataset.id) {
|
|
|
- _div.classList.add("activeModel");
|
|
|
- } else {
|
|
|
- el.classList.remove("activeModel");
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-//删除可移动元素
|
|
|
-export const deleteMoveNote = () => {
|
|
|
- for (let i = 0; i < moveData.modelList.length; i++) {
|
|
|
- const item: HTMLElement = document.querySelector(`[data-id=${moveData.modelList[i].id}]`)!;
|
|
|
- if (item?.classList?.contains("activeModel")) {
|
|
|
- moveData.modelList[i].isMove = true;
|
|
|
- undoData.undoList.push({ ...moveData.modelList[i] });
|
|
|
- moveData.modelList[i].isDelete = true;
|
|
|
- setModelPostion(moveData.modelList[i]);
|
|
|
- return;
|
|
|
- }
|
|
|
+/** 删除元素 */
|
|
|
+const handleDeleteMoveNote = () => {
|
|
|
+ const item = moveData.modelList[moveData.activeIndex];
|
|
|
+ if (item) {
|
|
|
+ moveData.modelList[moveData.activeIndex].isMove = true;
|
|
|
+ undoData.undoList.push({ ...moveData.modelList[moveData.activeIndex] });
|
|
|
+ moveData.modelList[moveData.activeIndex].isDelete = !item.isDelete;
|
|
|
+ const g = document.querySelector("#" + item.id)!;
|
|
|
+ g && ((g as any).style.display = moveData.modelList[moveData.activeIndex].isDelete ? "none" : '');
|
|
|
+ } else {
|
|
|
+ showToast("选中需要删除的元素");
|
|
|
}
|
|
|
- showToast("选中需要删除的元素");
|
|
|
};
|
|
|
-//重置数据
|
|
|
-export const resetMoveNote = () => {
|
|
|
+
|
|
|
+/** 重置数据 */
|
|
|
+const resetMoveNote = () => {
|
|
|
for (let i = 0; i < moveData.modelList.length; i++) {
|
|
|
moveData.modelList[i].x = 0;
|
|
|
moveData.modelList[i].y = 0;
|
|
|
moveData.modelList[i].isMove = false;
|
|
|
moveData.modelList[i].isDelete = false;
|
|
|
moveData.modelList[i].dx = 0;
|
|
|
- setModelPostion(moveData.modelList[i]);
|
|
|
+ renderSvgItem(moveData.modelList[i]);
|
|
|
if (moveData.modelList[i].type === "vf-lineGroup") {
|
|
|
renderLineGroup(moveData.modelList[i]);
|
|
|
}
|
|
@@ -326,7 +294,7 @@ function clearActiveModel() {
|
|
|
}
|
|
|
|
|
|
// 增加或减少, 渐强和渐弱的线长
|
|
|
-export const addAndSub = (type: string) => {
|
|
|
+const handleAddAndSub = (type: 'add' | 'sub') => {
|
|
|
if (!["add", "sub"].includes(type)) return;
|
|
|
const lineGroup = moveData.modelList[moveData.activeIndex];
|
|
|
if (!lineGroup || lineGroup.type !== "vf-lineGroup") return;
|
|
@@ -392,21 +360,50 @@ function renderLineGroup(lineGroup: any) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 撤销
|
|
|
-export const handleUndo = () => {
|
|
|
+/** 撤销 */
|
|
|
+const handleUndo = () => {
|
|
|
const preItem = undoData.undoList.pop();
|
|
|
// console.log("🚀 ~ preItem", preItem)
|
|
|
if (preItem) {
|
|
|
const itemIndex = moveData.modelList.findIndex((n: any) => n.id === preItem.id);
|
|
|
if (itemIndex > -1) {
|
|
|
moveData.modelList[itemIndex] = preItem;
|
|
|
- setModelPostion(preItem);
|
|
|
+ renderSvgItem(moveData.modelList[itemIndex])
|
|
|
if (preItem.type === "vf-lineGroup") {
|
|
|
renderLineGroup(preItem);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- console.log(undoData.undoList);
|
|
|
+};
|
|
|
+
|
|
|
+/** 根据移动数据渲染 */
|
|
|
+const renderForMoveData = () => {
|
|
|
+ if (state.extStyleConfigJson) {
|
|
|
+ try {
|
|
|
+ extStyleConfigJson = JSON.parse(state.extStyleConfigJson);
|
|
|
+ } catch (error) {
|
|
|
+ extStyleConfigJson = {};
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!extStyleConfigJson || !extStyleConfigJson?.[moveData.partIndex]) return;
|
|
|
+ const list = extStyleConfigJson?.[moveData.partIndex];
|
|
|
+ if (list && Array.isArray(list)) {
|
|
|
+ console.log("🚀 ~ list", list);
|
|
|
+ list.forEach((item: any) => {
|
|
|
+ const index = moveData.modelList.findIndex((n: any) => n.id === item.id);
|
|
|
+ if (index > -1) {
|
|
|
+ moveData.modelList[index] = {
|
|
|
+ ...moveData.modelList[index],
|
|
|
+ ...item
|
|
|
+ };
|
|
|
+ renderSvgItem(moveData.modelList[index]);
|
|
|
+ if (item.type === "vf-lineGroup") {
|
|
|
+ renderLineGroup(moveData.modelList[index]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
export default defineComponent({
|
|
@@ -419,9 +416,50 @@ export default defineComponent({
|
|
|
if (isOpen) {
|
|
|
initSvgId();
|
|
|
}
|
|
|
- if (detailData_gym.extStyleConfigJson) {
|
|
|
- }
|
|
|
+ renderForMoveData();
|
|
|
+ const toolBox = document.getElementById("toolBox");
|
|
|
+ toolBox && document.body.appendChild(toolBox);
|
|
|
});
|
|
|
- return () => <div></div>;
|
|
|
+ return () => (
|
|
|
+ <div class={[moveData.open ? "" : styles.moveDisabled]}>
|
|
|
+ <div class={styles.toolBox} id="toolBox">
|
|
|
+ <Switch v-model={moveData.open} />
|
|
|
+ {moveData.open && (
|
|
|
+ <>
|
|
|
+ {moveData.tool.isAddAndSub && (
|
|
|
+ <ButtonGroup size="small" elevation={false}>
|
|
|
+ <Button onClick={() => handleAddAndSub('add')}>加</Button>
|
|
|
+ <Button onClick={() => handleAddAndSub('sub')}>减</Button>
|
|
|
+ </ButtonGroup>
|
|
|
+ )}
|
|
|
+ {/* <ButtonGroup size="small">
|
|
|
+
|
|
|
+ <Button>
|
|
|
+ <Icon name="arrow-down" style={{ transform: "rotate(-90deg)" }} />
|
|
|
+ </Button>
|
|
|
+ </ButtonGroup> */}
|
|
|
+ <Button size="small" onClick={handleUndo} disabled={undoData.undoList.length ? false : true}>
|
|
|
+ <Icon name="arrow-down" style={{ transform: "rotate(90deg)" }} />
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button size="small" onClick={handleDeleteMoveNote} disabled={moveData.activeIndex > -1 ? false : true}>
|
|
|
+ {moveData.modelList[moveData.activeIndex]?.isDelete ? '显示元素' : '删除元素'}
|
|
|
+ </Button>
|
|
|
+ <Button size="small" onClick={resetMoveNote}>
|
|
|
+ 重置数据
|
|
|
+ </Button>
|
|
|
+ <Button size="small" type="primary" onClick={filterMoveData}>
|
|
|
+ 保存数据
|
|
|
+ </Button>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ {moveData.modelList.map((item: any, index: number) => {
|
|
|
+ return (
|
|
|
+ <div class={[styles.noteMove, moveData.activeIndex === index && styles.activeModel]} style={item.bbox} data-id={item.id} onMousedown={onDown}></div>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
},
|
|
|
});
|