|
|
@@ -0,0 +1,174 @@
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ class="video-preview"
|
|
|
+ :style="{
|
|
|
+ position: 'fixed',
|
|
|
+ left: posX + 'px',
|
|
|
+ top: posY + 'px',
|
|
|
+ width: boxWidth + 'px',
|
|
|
+ height: boxHeight + 'px',
|
|
|
+ cursor: cursor,
|
|
|
+ }"
|
|
|
+ @mousedown="startDrag"
|
|
|
+ @mousemove="changeCursor"
|
|
|
+ >
|
|
|
+ <el-icon :size="20" class="preview-close" @click="closeVideo"><Close /></el-icon>
|
|
|
+ <LiveVideo :url="props.videoUrl" />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+ import { ref } from 'vue';
|
|
|
+ import LiveVideo from '@/components/LiveVideo/LiveVideo.vue';
|
|
|
+ import { Close } from '@element-plus/icons-vue';
|
|
|
+ import { onMounted } from 'vue';
|
|
|
+
|
|
|
+ const props = defineProps<{
|
|
|
+ lastPosX: number;
|
|
|
+ lastPosY: number;
|
|
|
+ videoUrl: string;
|
|
|
+ }>();
|
|
|
+ const emit = defineEmits(['close']);
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ posX.value = props.lastPosX;
|
|
|
+ posY.value = props.lastPosY;
|
|
|
+ });
|
|
|
+
|
|
|
+ const posX = ref<number>();
|
|
|
+ const posY = ref<number>();
|
|
|
+
|
|
|
+ const scaleDistance = 10;
|
|
|
+ const boxWidth = ref<number>(400);
|
|
|
+ const boxHeight = ref<number>(300);
|
|
|
+
|
|
|
+ const isResizing = ref<boolean>(false);
|
|
|
+ const initialWidth = ref<number>(0);
|
|
|
+ const initialHeight = ref<number>(0);
|
|
|
+ const initialMouseX = ref<number>(0);
|
|
|
+ const initialMouseY = ref<number>(0);
|
|
|
+ const isTopLeft = ref<boolean>(false);
|
|
|
+ const isBottomLeft = ref<boolean>(false);
|
|
|
+ const isBottomRight = ref<boolean>(false);
|
|
|
+ const initialPosX = ref<number>(0);
|
|
|
+ const initialPosY = ref<number>(0);
|
|
|
+ const cursor = ref<string>('default');
|
|
|
+
|
|
|
+ const startDrag = (e) => {
|
|
|
+ const rect = e.target.getBoundingClientRect();
|
|
|
+ const offsetX = e.clientX - rect.left;
|
|
|
+ const offsetY = e.clientY - rect.top;
|
|
|
+ isTopLeft.value = Math.abs(offsetX) < scaleDistance && Math.abs(offsetY) < scaleDistance;
|
|
|
+ isBottomLeft.value =
|
|
|
+ Math.abs(offsetX) < scaleDistance && Math.abs(offsetY - rect.height) < scaleDistance;
|
|
|
+
|
|
|
+ isBottomRight.value =
|
|
|
+ Math.abs(offsetX - rect.width) < scaleDistance &&
|
|
|
+ Math.abs(offsetY - rect.height) < scaleDistance;
|
|
|
+
|
|
|
+ if (isTopLeft.value || isBottomLeft.value || isBottomRight.value) {
|
|
|
+ isResizing.value = true;
|
|
|
+ initialWidth.value = boxWidth.value;
|
|
|
+ initialHeight.value = boxHeight.value;
|
|
|
+ initialMouseX.value = e.clientX;
|
|
|
+ initialMouseY.value = e.clientY;
|
|
|
+ initialPosX.value = posX.value!;
|
|
|
+ initialPosY.value = posY.value!;
|
|
|
+ window.addEventListener('mousemove', handleResize);
|
|
|
+ window.addEventListener('mouseup', stopResize);
|
|
|
+ } else {
|
|
|
+ initialMouseX.value = e.clientX;
|
|
|
+ initialMouseY.value = e.clientY;
|
|
|
+ window.addEventListener('mousemove', handleMove);
|
|
|
+ window.addEventListener('mouseup', stopMove);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const changeCursor = (e) => {
|
|
|
+ const rect = e.target.getBoundingClientRect();
|
|
|
+ const offsetX = e.clientX - rect.left;
|
|
|
+ const offsetY = e.clientY - rect.top;
|
|
|
+ const isTopLeftMove = Math.abs(offsetX) < scaleDistance && Math.abs(offsetY) < scaleDistance;
|
|
|
+ const isBottomLeftMove =
|
|
|
+ Math.abs(offsetX) < scaleDistance && Math.abs(offsetY - rect.height) < scaleDistance;
|
|
|
+ const isBottomRightMove =
|
|
|
+ Math.abs(offsetX - rect.width) < scaleDistance &&
|
|
|
+ Math.abs(offsetY - rect.height) < scaleDistance;
|
|
|
+
|
|
|
+ if (isTopLeftMove || isBottomRightMove) {
|
|
|
+ cursor.value = 'nwse-resize';
|
|
|
+ } else if (isBottomLeftMove) {
|
|
|
+ cursor.value = 'nesw-resize';
|
|
|
+ } else {
|
|
|
+ cursor.value = 'default';
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleResize = (e) => {
|
|
|
+ const deltaX = e.clientX - initialMouseX.value;
|
|
|
+ const deltaY = e.clientY - initialMouseY.value;
|
|
|
+ boxWidth.value = initialWidth.value + deltaX;
|
|
|
+ boxHeight.value = initialHeight.value + deltaY;
|
|
|
+ if (isTopLeft.value) {
|
|
|
+ posX.value = initialPosX.value + deltaX;
|
|
|
+ posY.value = initialPosY.value + deltaY;
|
|
|
+ } else if (isBottomLeft.value) {
|
|
|
+ posX.value = initialPosX.value + deltaX;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (
|
|
|
+ (isTopLeft.value && deltaX < 0) ||
|
|
|
+ (isBottomLeft.value && deltaX < 0) ||
|
|
|
+ (isBottomRight.value && deltaX > 0)
|
|
|
+ ) {
|
|
|
+ boxWidth.value = initialWidth.value + Math.abs(deltaX);
|
|
|
+ boxHeight.value = initialHeight.value + Math.abs(deltaY);
|
|
|
+ } else {
|
|
|
+ boxWidth.value = initialWidth.value - Math.abs(deltaX);
|
|
|
+ boxHeight.value = initialHeight.value - Math.abs(deltaY);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleMove = (e) => {
|
|
|
+ const deltaX = e.clientX - initialMouseX.value;
|
|
|
+ const deltaY = e.clientY - initialMouseY.value;
|
|
|
+
|
|
|
+ posX.value = posX.value! + deltaX;
|
|
|
+ posY.value = posY.value! + deltaY!;
|
|
|
+
|
|
|
+ initialMouseX.value = e.clientX;
|
|
|
+ initialMouseY.value = e.clientY;
|
|
|
+ };
|
|
|
+
|
|
|
+ const stopResize = () => {
|
|
|
+ isResizing.value = false;
|
|
|
+ cursor.value = 'default';
|
|
|
+ window.removeEventListener('mousemove', handleResize);
|
|
|
+ window.removeEventListener('mouseup', stopResize);
|
|
|
+ };
|
|
|
+
|
|
|
+ const stopMove = () => {
|
|
|
+ window.removeEventListener('mousemove', handleMove);
|
|
|
+ window.removeEventListener('mouseup', stopMove);
|
|
|
+ };
|
|
|
+
|
|
|
+ const closeVideo = () => {
|
|
|
+ emit('close');
|
|
|
+ };
|
|
|
+</script>
|
|
|
+<style scoped>
|
|
|
+ .video-preview {
|
|
|
+ width: 400px;
|
|
|
+ height: 300px;
|
|
|
+ background-color: #a3a5a5;
|
|
|
+ position: relative;
|
|
|
+ z-index: 8;
|
|
|
+ }
|
|
|
+
|
|
|
+ .preview-close {
|
|
|
+ position: absolute;
|
|
|
+ top: 2px;
|
|
|
+ right: 2px;
|
|
|
+ z-index: 99;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+</style>
|