mini画布印花操作同步

This commit is contained in:
李志鹏
2026-01-09 16:41:49 +08:00
parent 88bd58fc66
commit 3058adfdb7
2 changed files with 302 additions and 42 deletions

View File

@@ -1,6 +1,27 @@
<template>
<div class="test">
<div class="control" v-for="(item, index) in list" :key="index">
<div
class="control"
:class="{ active: item.id === activeId }"
v-for="(item, index) in list"
:key="item.id"
@click="onSelect(item.id)"
>
<div>
<b>{{ item.name }}</b>
<button
v-if="index !== 0"
@click="onMove(item.id, list[index - 1].id)"
>
</button>
<button
v-if="index !== list.length - 1"
@click="onMove(item.id, list[index + 1].id)"
>
</button>
</div>
<div>
<span>偏移X</span>
<input type="number" v-model="item.location[0]" />
@@ -15,7 +36,7 @@
</div>
<div>
<span>缩放</span>
<input type="number" v-model="item.scale" />
<input type="number" v-model="item.scale[0]" />
</div>
<div>
<span>水平间距</span>
@@ -26,6 +47,7 @@
<input type="number" v-model="item.object.gapY" />
</div>
<hr />
<hr />
<div>
<span>缩放X</span>
<input type="number" v-model="item.object.scaleX" step="0.1" />
@@ -42,6 +64,11 @@
<span>Y</span>
<input type="number" v-model="item.object.top" />
</div>
<div>
<span>角度</span>
<input type="number" v-model="item.object.angle" />
</div>
<div>
<span>透明度</span>
<input
@@ -54,7 +81,11 @@
</div>
</div>
<div class="box">
<pingpu :list="list" ref="pingpuRef" />
<pingpu
:list="list"
ref="pingpuRef"
@change-canvas="updateCanvas"
/>
</div>
</div>
</template>
@@ -62,9 +93,16 @@
<script lang="ts" setup>
import { ref, onMounted, watch } from "vue";
import pingpu from "./pingpu.vue";
const ACTIONS = {
SELECT: "select",
UPDATE: "update",
DELETE: "delete",
SORT: "sort",
};
const convertDotNotationToBracket = (str) =>
str.replace(/(?:^|\.)(\d+)(?=\.|$)/g, "[#$1]").replace(/\[#/g, "[");
const activeId = ref("1");
const list = ref([
{
id: "1",
@@ -75,7 +113,7 @@
location: [0, 0],
scale: [1, 1],
angle: 0,
name: "Print2",
name: "Print1",
priority: 1,
object: {
top: 0,
@@ -121,11 +159,64 @@
const deepCopy = (obj) => JSON.parse(JSON.stringify(obj));
const oldList = ref(deepCopy(list.value));
const pingpuRef = ref(null);
const updateCanvas = (arr) => {
oldList.value = deepCopy(list.value);
arr.forEach((item) => {
list.value.forEach((v) => {
if (item.action === ACTIONS.UPDATE) {
if (v.id === item.id) {
if (item.action === ACTIONS.UPDATE) {
try {
const key = item.key;
const str = /^\[/.test(item.key)
? "v" + key
: "v." + key;
eval(`${str} = item.value`);
} catch (error) {
console.error(error);
}
}
}
} else if (item.action === ACTIONS.SELECT) {
activeId.value = item.id;
}
});
});
};
const onSelect = (id) => {
activeId.value = id;
pingpuRef.value.updataList([
{
id: id,
action: ACTIONS.SELECT,
},
]);
};
const onMove = (id, id2) => {
const obj1 = list.value.find((v) => v.id === id);
const obj2 = list.value.find((v) => v.id === id2);
const index1 = list.value.indexOf(obj1);
const index2 = list.value.indexOf(obj2);
if (index1 < index2) {
list.value.splice(index2, 0, list.value.splice(index1, 1)[0]);
} else {
list.value.splice(index1, 0, list.value.splice(index2, 1)[0]);
}
const ids = list.value.map((v) => v.id);
pingpuRef.value.updataList([
{
action: ACTIONS.SORT,
ids,
},
]);
};
watch(
() => list.value,
() => updateList(),
{ deep: true }
);
// 监听列表变化属性变更
const updateList = () => {
const changeList = [];
oldList.value.forEach((oldItem) => {
@@ -136,19 +227,18 @@
changeList.push({
...item,
id: oldItem.id,
action: "update-item",
action: ACTIONS.UPDATE,
key: convertDotNotationToBracket(item.key),
});
});
} else {
changeList.push({
id: oldItem.id,
action: "delete-item",
action: ACTIONS.DELETE,
});
}
});
oldList.value = deepCopy(list.value);
console.log(changeList);
if (changeList.length) {
pingpuRef.value.updataList(changeList);
}
@@ -161,8 +251,7 @@
} else if (obj1[key] !== obj2[key]) {
diffProps.push({
key: `${path}${key}`,
oldValue: obj1[key],
newValue: obj2[key],
value: obj2[key],
});
}
}
@@ -178,14 +267,24 @@
padding: 10px;
margin: 10px;
border-radius: 10px;
&.active {
border-color: rgb(17, 68, 223);
box-shadow: 0 0 5px rgb(17, 68, 223);
}
> div {
display: flex;
align-items: center;
margin-bottom: 5px;
> * {
margin-right: 10px;
&:last-child {
margin-right: 0;
}
}
> span {
width: 80px;
}
> input {
> input:not([type="range"]) {
padding-left: 10px;
border-radius: 5px;
}