Browse Source

优化拖动

caner 2 years ago
parent
commit
409261c743
2 changed files with 214 additions and 181 deletions
  1. 210 169
      src/App.vue
  2. 4 12
      src/components/icon.vue

+ 210 - 169
src/App.vue

@@ -1,112 +1,114 @@
-
 <script setup lang="ts">
 import { ref } from 'vue'
-
-const capBox = ref({ left: '10px', top: '10px', width: '0px', height: '0px' })
-const capImg = ref({ width: window.innerWidth + 'px', height: window.innerHeight + 'px', transform: 'translate(-5px,-5px)' })
-const toolStyle = ref({ left: '10px', top: '10px' })
-const showTool = ref(false)
+const bigBox = ref({ width: window.innerWidth + 'px', height: window.innerHeight + 'px' })
+const capBox = ref({ width: '0px', height: '0px', display: 'none', transform: 'translate(0px,0px)' })
+const capImg = ref({ width: window.innerWidth + 'px', height: window.innerHeight + 'px', transform: 'translate(0px,0px)' })
+const toolStyle = ref({ transform: 'translate(0, 0)', display: 'none' })
+const capboxDom = ref()
 
 function capBoxMove(e: any) {
     const dom = e.target
-    const sx = e.layerX
-    const sy = e.layerY
-    showTool.value = false
+    const sx = e.clientX
+    const sy = e.clientY
     const who = dom.dataset.id
-    console.log(666, e);
-
-    // let pdom = e.target.parentElement
-    // while (window.getComputedStyle(pdom).position !== 'relative' && pdom !== document.body) {
-    //     pdom = pdom.parentElement
-    // }
+    const oldTW = +capBox.value.transform.split('px')[0].split('(')[1]
+    const oldTH = +capBox.value.transform.split('px')[1].split(',')[1]
+    const capW = +capBox.value.width.replace('px', '')
+    const capH = +capBox.value.height.replace('px', '')
+    console.log(1, who);
 
-    if (who === 'screen') {
-        capBox.value.width = '0px'
-        capBox.value.height = '0px'
-        capBox.value.left = sx + 'px'
-        capBox.value.top = sy + 'px'
-    }else if(who === 'close'){
+    if (who === 'screen' || who === 'close') {
         capBox.value.width = '0px'
         capBox.value.height = '0px'
-        showTool.value = false
+        capBox.value.display = 'none'
     }
 
-    // const cW = +window.getComputedStyle(dom).width.replace('px', '')
-    // const cH = +window.getComputedStyle(dom).height.replace('px', '')
     document.onmousemove = em => {
+        const x = em.clientX - sx
+        const y = em.clientY - sy
         if (who === 'screen') {
-            const w = em.x - sx
-            const h = em.y - sy
-            if (w >= 0 && h >= 0) {
+            // 画框
+            capBox.value.display = 'block'
+            capBox.value.width = x + 'px'
+            capBox.value.height = y + 'px'
+            capBox.value.transform = `translate(${sx}px,${sy}px)`
+            capImg.value.transform = `translate(${-sx}px,${-sy}px)`
+            toolStyle.value.transform = `translate(${em.clientX - 200}px,${em.clientY + 10}px)`
+
+        } else if (who === 'move') {
+            // 移动
+            const w = x + oldTW
+            const h = y + oldTH
+            capBox.value.transform = `translate(${w}px,${h}px)`
+            capImg.value.transform = `translate(${-w}px,${-h}px)`
+            toolStyle.value.transform = `translate(${w + capW - 200}px,${h + capH + 10}px)`
+
+        } else if (who === 'right-bottom' || who === 'right-center' || who === 'bottom-center') {
+            // 右下 右中 下中
+            const w = x + capW
+            const h = y + capH
+            if (who === 'right-center') {
                 capBox.value.width = w + 'px'
+                toolStyle.value.transform = `translate(${oldTW + w - 200}px,${oldTH + capH + 10}px)`
+            } else if (who === 'bottom-center') {
                 capBox.value.height = h + 'px'
-                toolStyle.value.left = (em.x - 200) + 'px'
-                toolStyle.value.top = (em.y + 20) + 'px'
-                capImg.value.transform = `translate(${w}px,${h}px)`
+                toolStyle.value.transform = `translate(${oldTW + capW - 200}px,${oldTH + h + 10}px)`
+            } else {
+                capBox.value.width = w + 'px'
+                capBox.value.height = h + 'px'
+                toolStyle.value.transform = `translate(${oldTW + w - 200}px,${oldTH + h + 10}px)`
             }
-
         }
-        // const x = e.x - cW / 2
-        // const y = e.y - cH / 2
-
-        // // 移动
-        // if (dom.className === 'screen-box-border') {
-        //     // 计算移动当前元素的位置,并且给该元素样式中的left和top值赋值
-        //     dom.parentElement.style.left = x + 'px'
-        //     dom.parentElement.style.top = y + 'px'
-        // } else if (dom.className === 'screen-box-border-right-bottom') {
-        //     // 改变宽高
-        //     console.log(123, x, y, dom.parentElement);
-        //     const w = x - dom.parentElement.offsetLeft
-        //     const h = y - dom.parentElement.offsetTop
-        //     dom.parentElement.parentElement.style.width = w + cW + 'px'
-        //     dom.parentElement.parentElement.style.height = h + cH + 'px'
-        // }
-
-    }
-    document.onmouseup = () => {
-        document.onmousemove = null
-        document.onmouseup = null
-        document.onselectstart = null
-        showTool.value = !!+capBox.value.width.replace('px', '')
     }
+    document.onmouseup = close
 }
 
 function close() {
-    showTool.value = false
+    document.onmousemove = null
+    document.onmouseup = null
+    document.onselectstart = null
+    const capW = capBox.value.width.replace('px', '')
+    toolStyle.value.display = +capW ? 'flex' : 'none'
 }
-
 </script>
 <template>
-    <div class="screen" @mousedown="capBoxMove">
-        <img class="screenshots-background-image" src="https://nashaofu.github.io/screenshots/assets/image-5cf1218d.jpg">
-        <!-- mark -->
-        <div class="screen-mark" data-id="screen"></div>
+    <div class="screen" @mousedown="capBoxMove" :style="bigBox">
+        <div class="screen-background">
+            <img class="screen-background-image" src="https://nashaofu.github.io/screenshots/assets/image-5cf1218d.jpg">
+            <div class="screen-background-mark" data-id="screen"></div>
+        </div>
         <!-- capBox -->
-        <div class="screen-box" :style="capBox">
-            <div class="screen-box-border">
+        <div class="screen-box" ref="capboxDom" :style="capBox">
+
+            <div class="screen-box-img">
                 <img class="screen-box-border-image" :style="capImg"
-                    src="https://nashaofu.github.io/screenshots/assets/image-5cf1218d.jpg" v-drag>
-
-                <div class="screen-box-border-top-left"></div>
-                <div class="screen-box-border-top-center"></div>
-                <div class="screen-box-border-top-right"></div>
-                <div class="screen-box-border-right-center"></div>
-                <div class="screen-box-border-right-bottom"></div>
-                <div class="screen-box-border-bottom-center"></div>
-                <div class="screen-box-border-bottom-left"></div>
-                <div class="screen-box-border-left-center"></div>
+                    src="https://nashaofu.github.io/screenshots/assets/image-5cf1218d.jpg">
+            </div>
+
+            <div class="screen-box-mask" data-id="move">
+                <div>{{ capBox.width.replace('px', '') }}x{{ capBox.height.replace('px', '') }}</div>
             </div>
 
-            <div class="screen-box-mark">120x120</div>
+            <div class="screen-box-top "></div>
+            <div class="screen-box-top-center circle"></div>
+            <div class="screen-box-top-right circle"></div>
+            <div class="screen-box-right "></div>
+            <div class="screen-box-right-center circle" data-id="right-center"></div>
+            <div class="screen-box-right-bottom circle" data-id="right-bottom"></div>
+            <div class="screen-box-bottom "></div>
+            <div class="screen-box-bottom-center circle" data-id="bottom-center"></div>
+            <div class="screen-box-bottom-left circle"></div>
+            <div class="screen-box-left "></div>
+            <div class="screen-box-left-center circle"></div>
+            <div class="screen-box-left-top circle"></div>
         </div>
         <!-- tool -->
-        <div class="screen-tool" v-if="showTool" :style="toolStyle">
+        <div class="screen-tool" :style="toolStyle">
             <icon name="rect" color="#333" :size="21" />
             <icon name="cicle" color="#333" :size="22" />
             <icon name="rightTop" color="#333" :size="22" />
             <icon name="font" color="#333" :size="22" />
-            <icon name="close" color="#333" :size="22" data-id="close"/>
+            <icon name="close" color="#333" :size="22" data-id="close" type="close" />
             <icon name="write" color="#333" :size="22" />
         </div>
 
@@ -120,149 +122,188 @@ function close() {
     overflow: hidden;
     position: relative;
 
-    img {
+    &-background {
+        position: relative;
         width: 100%;
         height: 100%;
-        user-select: none;
-        pointer-events: none;
-    }
 
-    &-mark {
-        position: absolute;
-        width: 100%;
-        height: 100%;
-        background-color: rgba($color: #000000, $alpha: 0.5);
-        left: 0;
-        top: 0;
-        z-index: 1;
+        &-image {
+            width: 100%;
+            height: 100%;
+            display: block;
+            border: none;
+            outline: none;
+            image-rendering: -webkit-optimize-contrast;
+        }
+
+        &-mark {
+            position: absolute;
+            width: 100%;
+            height: 100%;
+            left: 0;
+            top: 0;
+            z-index: 1;
+            background-color: rgba($color: #000000, $alpha: 0.5);
+        }
     }
 
+
+
+
     &-box {
         position: absolute;
-        width: 500px;
-        height: 500px;
+        width: 0;
+        height: 0;
         z-index: 5;
         left: 0;
         top: 0;
-        overflow: hidden;
+        will-change: width, height, transform;
         display: flex;
         align-items: center;
         justify-content: center;
         cursor: move;
 
-        &-border {
-            box-sizing: border-box;
-            border: solid 2px #39f;
-            width: calc(100% - 4px);
-            height: calc(100% - 4px);
-            font-size: 0;
+        &>div {
+            position: absolute;
+        }
+
+        &-mask,
+        &-img {
+            left: 0;
+            top: 0;
+            width: 100%;
+            height: 100%;
             overflow: hidden;
+        }
 
+        &-mask {
             &>div {
-                width: 7px;
-                height: 7px;
-                overflow: hidden;
-                background: #39f;
                 position: absolute;
-                border-radius: 50%;
+                padding: 5px;
+                background: rgba($color: #000000, $alpha: 0.5);
+                color: white;
+                font-size: 12px;
+                bottom: 8px;
+                left: 50%;
+                transform: translate(-50%, 0);
             }
+        }
 
-            &-top-left {
-                left: 0;
-                top: 0;
-                cursor: nw-resize;
-            }
+        .circle {
+            background-color: #39f;
+            width: 6px;
+            height: 6px;
+            border-radius: 50%;
+        }
 
-            &-top-right {
-                right: 0;
-                top: 0;
-                cursor: ne-resize;
-            }
+        &-top {
+            left: 0;
+            top: 0;
+            width: 100%;
+            height: 2px;
+            background-color: #39f;
+            pointer-events: none;
+        }
 
-            &-top-center {
-                top: 0;
-                left: 50%;
-                cursor: n-resize;
-            }
+        &-top-center {
+            left: 50%;
+            top: -2px;
+            pointer-events: none;
+            // cursor: ns-resize;
+        }
 
-            &-bottom-center {
-                bottom: 0;
-                left: 50%;
-                cursor: s-resize;
-            }
+        &-top-right {
+            top: -2px;
+            right: -2px;
+            pointer-events: none;
+            // cursor: nesw-resize;
+        }
 
-            &-bottom-left {
-                left: 0;
-                bottom: 0;
-                cursor: sw-resize;
-            }
+        &-right {
+            width: 2px;
+            height: 100%;
+            top: 0;
+            right: 0;
+            background-color: #39f;
+            pointer-events: none;
+        }
 
-            &-right-center {
-                right: 0;
-                top: 50%;
-                cursor: w-resize;
-            }
+        &-right-center {
+            right: -2px;
+            top: 50%;
+            cursor: ew-resize;
+        }
 
-            &-right-bottom {
-                right: 0;
-                bottom: 0;
-                cursor: se-resize;
-            }
+        &-right-bottom {
+            right: -2px;
+            bottom: -2px;
+            cursor: nwse-resize;
+        }
 
-            &-left-center {
-                left: 0;
-                top: 50%;
-                cursor: e-resize;
-            }
+        &-bottom {
+            width: 100%;
+            height: 2px;
+            bottom: 0;
+            right: 0;
+            background-color: #39f;
+            pointer-events: none;
         }
 
-        &-mark {
-            padding: 5px;
-            background: rgba($color: #000000, $alpha: 0.5);
-            color: white;
-            font-size: 12px;
-            position: absolute;
-            bottom: 8px;
+        &-bottom-center {
             left: 50%;
-            transform: translate(-50%, 0);
+            bottom: -2px;
+            cursor: ns-resize;
         }
 
+        &-bottom-left {
+            left: -2px;
+            bottom: -2px;
+            // cursor: nesw-resize;
+            pointer-events: none;
+        }
 
-    }
 
-    &-move-box {
-        position: absolute;
-        left: 0;
-        top: 0;
-        z-index: 6;
+        &-left {
+            height: 100%;
+            width: 2px;
+            top: 0;
+            left: 0;
+            background-color: #39f;
+            pointer-events: none;
+        }
 
-        &>p {
-            color: #fff;
-            font-size: 11px;
-            background-color: #5f5e5e;
-            padding: 5px;
-            white-space: nowrap;
-            overflow: hidden;
-            text-align: left;
-            margin: 0;
+        &-left-center {
+            top: 50%;
+            left: -2px;
+            pointer-events: none;
+            // cursor: ew-resize;
         }
+
+        &-left-top {
+            top: -2px;
+            left: -2px;
+            pointer-events: none;
+            // cursor: nwse-resize;
+        }
+
     }
 
     &-tool {
-        position: absolute;
         width: 200px;
-        height: 30px;
-        left: 300px;
-        top: 510px;
+        position: absolute;
         z-index: 6;
         background: white;
         border-radius: 3px;
         display: flex;
-        justify-content: space-evenly;
         align-items: center;
+        justify-content: space-evenly;
+        padding: 3px 0;
+        left: 0;
+        top: 0;
 
         &>svg {
             box-sizing: border-box;
+            margin: 0 3px;
         }
 
         &>svg:hover {

+ 4 - 12
src/components/icon.vue

@@ -3,23 +3,15 @@ import { computed } from 'vue'
 const props = defineProps<{
   name: string,
   size?: number,
-  color?: string
+  color?: string,
+  type?: string
 }>()
 const symbolId = computed(() => `#icon-${props.name}`)
 const newColor = computed(() => `${props.color ?? '#ccc'}`)
 const newSize = computed(() => `${props.size ?? 16}`)
 </script>
 <template>
-  <svg
-    aria-hidden="true"
-    :font-size="newSize"
-    :width="newSize"
-    :height="newSize"
-  >
-
-    <use
-      :href="symbolId"
-      :fill="newColor"
-    />
+  <svg aria-hidden="true" :font-size="newSize" :width="newSize" :height="newSize">
+    <use :href="symbolId" :fill="newColor" :data-id="type" />
   </svg>
 </template>