Bladeren bron

优化拖拽指令

Hwf 2 maanden geleden
bovenliggende
commit
c2e2c72a36
4 gewijzigde bestanden met toevoegingen van 91 en 109 verwijderingen
  1. 1 1
      src/components/Dialog/index.vue
  2. 57 93
      src/components/TimeAxis/index.vue
  3. 14 15
      src/directive/common/drag.ts
  4. 19 0
      src/types/components.d.ts

+ 1 - 1
src/components/Dialog/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div v-if="modelValue || customShow"  v-drag="{draggable: draggable, position: 'fixed', scaleX: containerScale().scaleX, scaleY: containerScale().scaleY}" class="common-dialog" :style="{ width: computedWidth, height: computedHeight, zIndex: zIndex }">
+  <div v-if="modelValue || customShow" v-drag="{ draggable: draggable, position: 'fixed', scale: containerScale, handle: '.dialog-header' }">
     <div :class="type === 'xs' || headerType === 'header2' ? 'dialog-header2' : 'dialog-header'">
       <div v-if="!hideTitle" class="dialog-title">
         {{ title ? title : '弹窗' }}

+ 57 - 93
src/components/TimeAxis/index.vue

@@ -1,43 +1,42 @@
 <template>
-  <div>
-    <div class="time-axis-container" :style="{ bottom: `${dragState.bottom}px`, left: `${dragState.left}px` }">
-      <div class="expand-btn" @click="changeExpand">{{ timeAxisState.expand ? '收起' : '展开' }}</div>
-      <div v-show="timeAxisState.expand" class="time-box">
-        <div class="time-picker-box">
-          <el-date-picker
-            v-model="timeAxisState.startTime"
-            type="datetime"
-            :editable="false"
-            :format="timeAxisState.format"
-            :value-format="timeAxisState.format"
-            :clearable="false"
-          />
-          <el-date-picker
-            v-model="timeAxisState.endTime"
-            type="datetime"
-            :editable="false"
-            :format="timeAxisState.format"
-            :value-format="timeAxisState.format"
-            :clearable="false"
+  <div v-drag="{ draggable: true, scale: containerScale, handle: '.rankIcon' }" class="time-axis-container">
+    <div class="expand-btn" @click="changeExpand">{{ timeAxisState.expand ? '收起' : '展开' }}</div>
+    <div v-show="timeAxisState.expand" class="time-box">
+      <div class="time-picker-box">
+        <el-date-picker
+          v-model="timeAxisState.startTime"
+          type="datetime"
+          :editable="false"
+          :format="timeAxisState.format"
+          :value-format="timeAxisState.format"
+          :clearable="false"
+        />
+        <el-date-picker
+          v-model="timeAxisState.endTime"
+          type="datetime"
+          :editable="false"
+          :format="timeAxisState.format"
+          :value-format="timeAxisState.format"
+          :clearable="false"
+        />
+      </div>
+      <div class="time-list-box">
+        <el-timeline>
+          <el-timeline-item
+            v-for="(activity, index) in timeAxisState.data"
+            :key="index"
+            :ref="(el) => (timelineItems[index] = el)"
+            :class="timeAxisState.activeIndex === index ? 'active' : ''"
+            :timestamp="activity.time"
           />
-        </div>
-        <div class="time-list-box">
-          <el-timeline>
-            <el-timeline-item
-              v-for="(activity, index) in timeAxisState.data"
-              :key="index"
-              :class="timeAxisState.activeIndex === index ? 'active' : ''"
-              :timestamp="activity.time"
-            />
-          </el-timeline>
-        </div>
-        <div class="time-tool">
-          <div class="prevIcon" @click="toPrevTime" />
-          <div class="playIcon" @click="toPlayTime" />
-          <div class="nextIcon" @click="toNextTime(true)" />
-          <div class="speed-btn" @click="changeSpeed">{{ timeAxisState.speed === 1 ? 'x1' : 'x2' }}</div>
-          <div class="rankIcon" @mousedown="startDrag" @mousemove="onDrag" @mouseup="stopDrag" @click="dragMove" />
-        </div>
+        </el-timeline>
+      </div>
+      <div class="time-tool">
+        <div class="prevIcon" @click="toPrevTime" />
+        <div class="playIcon" @click="toPlayTime" />
+        <div class="nextIcon" @click="toNextTime(true)" />
+        <div class="speed-btn" @click="changeSpeed">{{ timeAxisState.speed === 1 ? 'x1' : 'x2' }}</div>
+        <div class="rankIcon" />
       </div>
     </div>
   </div>
@@ -59,6 +58,7 @@ let mapUtils, map, AMap;
 let moveMarker, movePassedPolyline, movePolyline;
 let isNewMarkerPause = false;
 let trackPathArr = [];
+const timelineItems = ref([]);
 const timeAxisState = reactive({
   expand: false,
   type: '',
@@ -116,61 +116,6 @@ const changeSpeed = () => {
   timeAxisState.speed = timeAxisState.speed === 1 ? 2 : 1;
 };
 
-// 拖拽移动位置
-const dragMove = () => {};
-
-// 拖拽的参数
-const dragState = reactive({
-  bottom: 40,
-  left: 10,
-  dragging: false,
-  startX: 20,
-  startY: 20,
-  initialMouseX: 20,
-  initialMouseY: 20
-});
-
-// 开始拖拽
-const startDrag = (event) => {
-  dragState.dragging = true;
-  dragState.startX = dragState.left;
-  dragState.startY = dragState.bottom;
-  dragState.initialMouseX = event.clientX;
-  dragState.initialMouseY = event.clientY;
-  document.addEventListener('mousemove', onDrag);
-  document.addEventListener('mouseup', stopDrag2);
-};
-
-const onDrag = (event) => {
-  if (!dragState.dragging) return;
-  console.log(dragState.bottom + dragState.initialMouseY - event.clientY);
-  console.log(dragState.bottom, dragState.initialMouseY, event.clientY);
-  let left = (dragState.startX + event.clientX - dragState.initialMouseX) / containerScale().scaleX - 134;
-  let bottom = (dragState.startY + dragState.initialMouseY - event.clientY) / containerScale().scaleY - 134;
-  // // 检测是否溢出
-  // if (left < 0) {
-  //   left = 0;
-  // } else if (left > document.body.clientWidth - 1001) {
-  //   left = document.body.clientWidth - 1001;
-  // }
-  // if (bottom < 0) {
-  //   bottom = 0;
-  // } else if (bottom > document.body.clientHeight - 70) {
-  //   bottom = document.body.clientHeight - 70;
-  // }
-  dragState.left = left;
-  dragState.bottom = bottom;
-};
-
-const stopDrag = () => {
-  dragState.dragging = false;
-};
-const stopDrag2 = () => {
-  dragState.dragging = false;
-  document.removeEventListener('mousemove', onDrag);
-  document.removeEventListener('mouseup', stopDrag2);
-};
-
 // 外部数据传入,开始播放
 const initDataToPlay = (obj) => {
   timeAxisState.type = obj.type;
@@ -339,6 +284,23 @@ const getAngle = (startPoint, endPoint) => {
   return dRotateAngle;
 };
 
+// 滚动到可见到当前点位置
+watch(
+  () => timeAxisState.activeIndex,
+  (index) => {
+    nextTick(() => {
+      const itemRef = timelineItems.value[index];
+      if (itemRef) {
+        const itemEl = itemRef.$el;
+        console.log(itemEl);
+        itemEl.scrollIntoView({
+          behavior: 'smooth'
+        });
+      }
+    });
+  }
+);
+
 onMounted(() => {
   getInitTime();
 });
@@ -349,6 +311,8 @@ defineExpose({ initDataToPlay });
 <style lang="scss" scoped>
 .time-axis-container {
   position: absolute;
+  bottom: 40px;
+  left: 10px;
   z-index: 2;
   color: #fff;
   font-size: 14px;

+ 14 - 15
src/directive/common/drag.ts

@@ -1,32 +1,31 @@
 export default {
   mounted(el, binding) {
-    const { draggable, position = 'absolute', scaleX = 1, scaleY = 1, dom } = binding.value;
-    if (!draggable) {
+    const { draggable, position = 'absolute', scale = { scaleX: 1, scaleY: 1 }, handle } = binding.value;
+    // 获取触发拖拽的句柄元素(如标题栏)
+    const dragHandle = handle ? el.querySelector(handle) : el;
+    if (!draggable || !dragHandle) {
       // 如果拖拽功能被禁用,则不执行任何拖拽相关的逻辑
       return;
     }
-
+    console.log(scale().scaleX, scale().scaleY);
     el.style.position = position;
-    el.style.cursor = 'move';
-
-    const dragDom = !!dom ? dom : el;
-
     let disX = 0; // 鼠标按下时,鼠标与拖拽元素的左边距
     let disY = 0; // 鼠标按下时,鼠标与拖拽元素的上边距
-
-    dragDom.onmousedown = (e) => {
+    dragHandle.style.cursor = 'move';
+    dragHandle.onmousedown = (e) => {
+      console.log(scale());
       // 鼠标按下,计算当前元素距离可视区的距离
-      disX = e.clientX / scaleX - dragDom.offsetLeft;
-      disY = e.clientY / scaleY - dragDom.offsetTop;
+      disX = e.clientX / scale().scaleX - el.offsetLeft;
+      disY = e.clientY / scale().scaleY - el.offsetTop;
 
       // 鼠标移动事件
       document.onmousemove = function (e) {
         // 通过事件委托,计算移动的距离
-        const l = e.clientX / scaleX - disX;
-        const t = e.clientY / scaleY - disY;
+        const l = e.clientX / scale().scaleX - disX;
+        const t = e.clientY / scale().scaleY - disY;
         // 移动当前元素
-        dragDom.style.left = `${l + 'px'}`;
-        dragDom.style.top = `${t + 'px'}`;
+        el.style.left = `${l + 'px'}`;
+        el.style.top = `${t + 'px'}`;
 
         // 将此时的位置传出去
         // binding.value({x:e.pageX,y:e.pageY})

+ 19 - 0
src/types/components.d.ts

@@ -27,10 +27,16 @@ declare module 'vue' {
     ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCard: typeof import('element-plus/es')['ElCard']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+    ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
+    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
+    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -43,18 +49,28 @@ declare module 'vue' {
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
+    ElLink: typeof import('element-plus/es')['ElLink']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+    ElSegmented: typeof import('element-plus/es')['ElSegmented']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSlider: typeof import('element-plus/es')['ElSlider']
+    ElStep: typeof import('element-plus/es')['ElStep']
+    ElSteps: typeof import('element-plus/es')['ElSteps']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTabPane: typeof import('element-plus/es')['ElTabPane']
+    ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
@@ -74,6 +90,9 @@ declare module 'vue' {
     HikvisionPlayer: typeof import('./../components/HKVideo/hikvision-player.vue')['default']
     HKVideo: typeof import('./../components/HKVideo/index.vue')['default']
     IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
+    IEpCaretBottom: typeof import('~icons/ep/caret-bottom')['default']
+    IEpCaretTop: typeof import('~icons/ep/caret-top')['default']
+    IEpUploadFilled: typeof import('~icons/ep/upload-filled')['default']
     IFrame: typeof import('./../components/iFrame/index.vue')['default']
     ImagePreview: typeof import('./../components/ImagePreview/index.vue')['default']
     ImageUpload: typeof import('./../components/ImageUpload/index.vue')['default']