123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- <!-- eslint-disable vue/no-unused-vars -->
- <!-- eslint-disable vue/valid-v-for -->
- <template>
- <div ref="wrapRef" class="svg-wrap" @mousemove="handleMouseMove">
- <svg
- version="1.1"
- baseProfile="full"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:ev="http://www.w3.org/2001/xml-events"
- :width="wrapSize.width"
- :height="wrapSize.height"
- >
- <SvgRect
- v-for="i in children"
- :key="i.id"
- v-bind="i"
- :draggingId="draggingId"
- :mousePos="curPos"
- @startLine="startLine"
- @startDrag="startDrag"
- @updatePos="updatePos"
- />
- <line v-if="lineStartPoint" v-bind="dashLineAttr"></line>
- </svg>
- </div>
- </template>
- <script setup>
- import { reactive, ref, onBeforeUnmount, onMounted, computed } from "vue";
- import SvgRect from "./components/svgRect.vue";
- import { findFromArray, getPosFromEvent } from "./utils/index";
- const wrapRef = ref(null);
- const childrenRefs = ref(null);
- let curPos = ref({ x: 0, y: 0 });
- const wrapSize = reactive({ width: 0, height: 0 });
- const draggingId = ref(0);
- const lineStartPoint = ref(null);
- const children = ref([
- { id: 1, pos: { x: 10, y: 10 }, size: { width: 100, height: 100 } },
- { id: 2, pos: { x: 20, y: 20 }, size: { width: 100, height: 100 } },
- { id: 3, pos: { x: 30, y: 30 }, size: { width: 100, height: 100 } },
- ]);
- const dashLineAttr = computed(() => {
- if (lineStartPoint.value) {
- return {
- x1: lineStartPoint.value?.cx,
- y1: lineStartPoint.value?.cy,
- x2: curPos.value.x,
- y2: curPos.value.y,
- stroke: "black",
- "stroke-dasharray": "3 4",
- "stroke-width": "2",
- };
- }
- return {};
- });
- function startDrag({ id, event }) {
- draggingId.value = id;
- lineStartPoint.value = null;
- curPos.value = getPosFromEvent(event);
- const { index, result } = findFromArray(children.value, (i) => i.id === id);
- children.value.splice(index, 1);
- children.value.push(result);
- }
- function startLine({ id, point }) {
- draggingId.value = 0;
- lineStartPoint.value = point;
- }
- function updatePos({ id, pos }) {
- const { result } = findFromArray(children.value, (i) => i.id === id);
- result.pos = pos;
- }
- function handleMouseMove(e) {
- curPos.value = getPosFromEvent(e);
- }
- function handleMouseUp() {
- draggingId.value = 0;
- lineStartPoint.value = null;
- }
- function initSvgSize() {
- // 避免因为转rem时有小数误差导致得滚动条
- wrapSize.width = wrapRef.value.offsetWidth - 1;
- wrapSize.height = wrapRef.value.offsetHeight - 1;
- }
- window.addEventListener("mouseup", handleMouseUp);
- window.addEventListener("resize", initSvgSize);
- onMounted(() => {
- initSvgSize();
- });
- onBeforeUnmount(() => {
- window.removeEventListener("mouseup", handleMouseUp);
- window.removeEventListener("resize", initSvgSize);
- });
- </script>
- <style lang="less" scoped>
- .svg-wrap {
- min-height: 400px;
- background-color: blue;
- background-image: linear-gradient(
- transparent 0px,
- transparent 2px,
- #fff 2px,
- #fff 15px
- ),
- linear-gradient(90deg, #ccc 0px, #ccc 2px, #fff 2px, #fff 15px);
- background-size: 15px 15px, 15px 15px;
- position: relative;
- svg {
- display: block;
- }
- }
- </style>
|