Ver código fonte

优化拖拽指令

Hwf 2 meses atrás
pai
commit
551b898d82

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

@@ -1,7 +1,7 @@
 <template>
   <div
     v-if="modelValue || customShow"
-    v-drag="{ draggable: draggable, position: 'fixed', scaleX: containerScale().scaleX, scaleY: containerScale().scaleY }"
+    v-drag="{ draggable: draggable, position: 'fixed', scale: containerScale, handle: '.dialog-header' }"
     class="common-dialog"
     :style="{ width: computedWidth, height: computedHeight, zIndex: zIndex }"
   >

+ 57 - 97
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: '',
@@ -115,61 +115,6 @@ const changeSpeed = () => {
   timeAxisState.speed = timeAxisState.speed === 1 ? 2 : 1;
 };
 
-// 拖拽移动位置
-const dragMove = () => {};
-
-// 拖拽的参数
-const dragState = reactive({
-  bottom: 180,
-  left: 200,
-  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;
@@ -318,10 +263,7 @@ const getAngle = (startPoint, endPoint) => {
     return 0;
   }
 
-  let dRotateAngle = Math.atan2(
-    Math.abs(startPoint.lng - endPoint.lng),
-    Math.abs(startPoint.lat - endPoint.lat)
-  );
+  let dRotateAngle = Math.atan2(Math.abs(startPoint.lng - endPoint.lng), Math.abs(startPoint.lat - endPoint.lat));
   if (endPoint.lng >= startPoint.lng) {
     if (endPoint.lat >= startPoint.lat) {
     } else {
@@ -337,6 +279,22 @@ const getAngle = (startPoint, endPoint) => {
   dRotateAngle = (dRotateAngle * 180) / Math.PI;
   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();
@@ -348,6 +306,8 @@ defineExpose({ initDataToPlay });
 <style lang="scss" scoped>
 .time-axis-container {
   position: absolute;
+  bottom: 180px;
+  left: 200px;
   z-index: 2;
   color: #fff;
   font-size: 16px;

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

@@ -1,31 +1,35 @@
 export default {
   mounted(el, binding) {
-    const { draggable, position = 'absolute', scaleX = 1, scaleY = 1, dom } = binding.value;
-    if (!draggable) {
+    const { draggable, position = 'absolute', scale, handle } = binding.value;
+    // 获取触发拖拽的句柄元素(如标题栏)
+    const dragHandle = handle ? el.querySelector(handle) : el;
+    if (!draggable || !dragHandle) {
       // 如果拖拽功能被禁用,则不执行任何拖拽相关的逻辑
       return;
     }
-
+    let scaleMethod = scale;
+    if (dragHandle) {
+      scaleMethod = () => {
+        return { scaleX: 1, scaleY: 1 };
+      };
+    }
     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) => {
       // 鼠标按下,计算当前元素距离可视区的距离
-      disX = e.clientX / scaleX - dragDom.offsetLeft;
-      disY = e.clientY / scaleY - dragDom.offsetTop;
+      disX = e.clientX / scaleMethod().scaleX - el.offsetLeft;
+      disY = e.clientY / scaleMethod().scaleY - el.offsetTop;
 
       // 鼠标移动事件
       document.onmousemove = function (e) {
         // 通过事件委托,计算移动的距离
-        const l = e.clientX / scaleX - disX;
-        const t = e.clientY / scaleY - disY;
+        const l = e.clientX / scaleMethod().scaleX - disX;
+        const t = e.clientY / scaleMethod().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})