| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- <template>
- <div class="tel-view-tem" @mousedown="onMouseDown">
- <img class="bg-src" :src="bgSrc" />
- <!-- 拖动选区样式 -->
- <div v-if="isDragging" class="drag-area" :style="dragAreaStyle"></div>
- <div class="pro-content">
- <slot></slot>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, computed, watch } from 'vue';
- import { propTypes } from '@/utils/propTypes';
- const props = defineProps({
- width: propTypes.number.def(750),
- minHeight: propTypes.number.def(1000),
- bgColor: propTypes.string.def('#fff'),
- enableDraw: propTypes.bool.def(true),
- bgSrc: propTypes.string.def(''),
- });
- const emit = defineEmits(['selectArea']);
- const isDragging = ref(false);
- const startPoint = ref({ x: 0, y: 0 });
- const endPoint = ref({ x: 0, y: 0 });
- const imgHeight = ref(props.minHeight);
- const imgWidth = ref(props.width);
- const containerStyle: any = computed(() => {
- if (props.bgSrc) {
- return {
- width: props.width ? `${props.width}px` : '100%',
- height: `${imgHeight.value}px`,
- backgroundImage: `url(${props.bgSrc})`,
- backgroundSize: 'contain',
- backgroundRepeat: 'no-repeat',
- backgroundPosition: 'center',
- position: 'relative',
- userSelect: 'none',
- minHeight: `${imgHeight.value}px`,
- backgroundColor: props.bgColor,
- };
- }
- return {
- width: `${props.width}px`,
- minHeight: `${props.minHeight}px`,
- background: props.bgColor,
- position: 'relative',
- userSelect: 'none',
- };
- });
- const dragAreaStyle: any = 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: '2px dashed #409eff',
- background: 'rgba(116, 251, 229,0.3)',
- 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 {
- position: relative;
- z-index: 100;
- transition: none;
- }
- .bg-src {
- width: 750px;
- display: block;
- user-select: none;
- pointer-events: none;
- height: auto;
- object-fit: contain;
- z-index: -1;
- }
- .pro-content {
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- }
- </style>
|