|
@@ -0,0 +1,96 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="tel-view-tem" :style="{ width: `${width}px`, height: `${height}px`, background: bgColor, position: 'relative', userSelect: 'none' }" @mousedown="onMouseDown">
|
|
|
|
|
+ <!-- 拖动选区样式 -->
|
|
|
|
|
+ <div v-if="isDragging" class="drag-area" :style="dragAreaStyle"></div>
|
|
|
|
|
+ <slot></slot>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import { ref, computed } from 'vue';
|
|
|
|
|
+import { propTypes } from '@/utils/propTypes';
|
|
|
|
|
+
|
|
|
|
|
+const props = defineProps({
|
|
|
|
|
+ width: propTypes.number.def(750),
|
|
|
|
|
+ height: propTypes.number.def(1000),
|
|
|
|
|
+ bgColor: propTypes.string.def('#fff'),
|
|
|
|
|
+ enableDraw: propTypes.bool.def(true) // 新增开关属性
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const emit = defineEmits(['selectArea']);
|
|
|
|
|
+
|
|
|
|
|
+const isDragging = ref(false);
|
|
|
|
|
+const startPoint = ref({ x: 0, y: 0 });
|
|
|
|
|
+const endPoint = ref({ x: 0, y: 0 });
|
|
|
|
|
+
|
|
|
|
|
+const dragAreaStyle = computed(() => {
|
|
|
|
|
+ const x = Math.min(startPoint.value.x, endPoint.value.x);
|
|
|
|
|
+ const y = Math.min(startPoint.value.y, endPoint.value.y);
|
|
|
|
|
+ const w = Math.abs(endPoint.value.x - startPoint.value.x);
|
|
|
|
|
+ const h = Math.abs(endPoint.value.y - startPoint.value.y);
|
|
|
|
|
+ return {
|
|
|
|
|
+ position: 'absolute',
|
|
|
|
|
+ left: `${x}px`,
|
|
|
|
|
+ top: `${y}px`,
|
|
|
|
|
+ width: `${w}px`,
|
|
|
|
|
+ height: `${h}px`,
|
|
|
|
|
+ border: '1px dashed #409eff',
|
|
|
|
|
+ background: 'rgba(64,158,255,0.1)',
|
|
|
|
|
+ pointerEvents: 'none',
|
|
|
|
|
+ zIndex: 10,
|
|
|
|
|
+ };
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+function onMouseDown(e: MouseEvent) {
|
|
|
|
|
+ if (!props.enableDraw) return; // 根据开关属性决定是否允许绘制
|
|
|
|
|
+ if (e.button !== 0) return;
|
|
|
|
|
+ const rect = (e.target as HTMLElement).getBoundingClientRect();
|
|
|
|
|
+ startPoint.value = {
|
|
|
|
|
+ x: e.clientX - rect.left,
|
|
|
|
|
+ y: e.clientY - rect.top,
|
|
|
|
|
+ };
|
|
|
|
|
+ endPoint.value = { ...startPoint.value };
|
|
|
|
|
+ isDragging.value = true;
|
|
|
|
|
+
|
|
|
|
|
+ window.addEventListener('mousemove', onMouseMove);
|
|
|
|
|
+ window.addEventListener('mouseup', onMouseUp);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function onMouseMove(e: MouseEvent) {
|
|
|
|
|
+ if (!isDragging.value) return;
|
|
|
|
|
+ const rect = (e.target as HTMLElement).closest('.tel-view-tem')?.getBoundingClientRect();
|
|
|
|
|
+ if (!rect) return;
|
|
|
|
|
+ endPoint.value = {
|
|
|
|
|
+ x: e.clientX - rect.left,
|
|
|
|
|
+ y: e.clientY - rect.top,
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function onMouseUp() {
|
|
|
|
|
+ if (!isDragging.value) return;
|
|
|
|
|
+ isDragging.value = false;
|
|
|
|
|
+ emit('selectArea', {
|
|
|
|
|
+ start: { ...startPoint.value },
|
|
|
|
|
+ end: { ...endPoint.value },
|
|
|
|
|
+ rect: {
|
|
|
|
|
+ x: Math.min(startPoint.value.x, endPoint.value.x),
|
|
|
|
|
+ y: Math.min(startPoint.value.y, endPoint.value.y),
|
|
|
|
|
+ w: Math.abs(endPoint.value.x - startPoint.value.x),
|
|
|
|
|
+ h: Math.abs(endPoint.value.y - startPoint.value.y),
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+ window.removeEventListener('mousemove', onMouseMove);
|
|
|
|
|
+ window.removeEventListener('mouseup', onMouseUp);
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+.tel-view-tem {
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+}
|
|
|
|
|
+.drag-area {
|
|
|
|
|
+ transition: none;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|