Pārlūkot izejas kodu

网格线优化

pipipi-pikachu 5 gadi atpakaļ
vecāks
revīzija
c77dfb4c5a

+ 58 - 26
src/views/Editor/Canvas/GridLines.vue

@@ -1,39 +1,69 @@
 <template>
-  <div 
-    class="grid-lines"
-    :style="style"
-  ></div>
+  <SvgWrapper class="grid-lines">
+    <path 
+      :style="{
+        transform: `scale(${canvasScale})`,
+      }" 
+      :d="path" 
+      fill="none" 
+      :stroke="gridColor" 
+      stroke-width="0.3" 
+      shape-rendering="crispEdges"
+      stroke-dasharray="5"
+    ></path>
+  </SvgWrapper>
 </template>
 
 <script lang="ts">
-import { defineComponent, computed } from 'vue'
+import { defineComponent, computed, Ref } from 'vue'
+import { useStore } from 'vuex'
+import tinycolor from 'tinycolor2'
+import { State } from '@/store'
+import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
+import { SlideBackground } from '@/types/slides'
 
 export default defineComponent({
   name: 'grid-lines',
-  props: {
-    gridSize: {
-      type: Number,
-      default: 20,
-    },
-    gridColor: {
-      type: String,
-      default: 'rgba(100, 100, 100, 0.1)',
-    },
-  },
   setup(props) {
-    const style = computed(() => {
-      const gridSize = props.gridSize + 'px'
-      const gridSpacing = props.gridSize - 1 + 'px'
-      const gridColor = props.gridColor
-
-      return {
-        backgroundImage: `linear-gradient(transparent ${gridSpacing}, ${gridColor} ${gridSpacing}, ${gridColor} ${gridSize}), linear-gradient(90deg, transparent ${gridSpacing}, ${gridColor} ${gridSpacing}, ${gridColor} ${gridSize})`,
-        backgroundSize: `${gridSize} ${gridSize}`,
+    const store = useStore<State>()
+    const canvasScale = computed(() => store.state.canvasScale)
+    const background: Ref<SlideBackground | undefined> = computed(() => store.getters.currentSlide.background)
+
+    const gridColor = computed(() => {
+      if(!background.value || background.value.type === 'image') return 'rgba(100, 100, 100, 0.5)'
+      const color = background.value.value
+      const rgba = tinycolor(color).toRgb()
+      const newRgba = {
+        r: rgba.r > 128 ? rgba.r - 128 : rgba.r + 127,
+        g: rgba.g > 128 ? rgba.g - 128 : rgba.g + 127,
+        b: rgba.b > 128 ? rgba.b - 128 : rgba.b + 127,
+        a: 0.5
       }
+      return `rgba(${[newRgba.r, newRgba.g, newRgba.b, newRgba.a].join(',')})`
     })
 
+    const gridSize = 50
+
+    const getPath = () => {
+      const maxX = VIEWPORT_SIZE
+      const maxY = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO
+
+      let path = ''
+      for(let i = 0; i <= Math.floor(maxY / gridSize); i++) {
+        path += `M0 ${i * gridSize}, L${maxX} ${i * gridSize}`
+      }
+      for(let i = 0; i <= Math.floor(maxX / gridSize); i++) {
+        path += `M${i * gridSize} 0, L${i * gridSize} ${maxY}`
+      }
+      return path
+    }
+
     return {
-      style,
+      canvasScale,
+      gridColor,
+      width: VIEWPORT_SIZE,
+      height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,
+      path: getPath(),
     }
   },
 })
@@ -41,11 +71,13 @@ export default defineComponent({
 
 <style lang="scss" scoped>
 .grid-lines {
+  width: 100%;
+  height: 100%;
   position: absolute;
   top: 0;
-  bottom: 0;
   left: 0;
+  bottom: 0;
   right: 0;
-  background-position: 0 0;
+  overflow: visible;
 }
 </style>

+ 1 - 4
src/views/Editor/Canvas/SlideBackground.vue

@@ -3,10 +3,7 @@
     class="slide-background"
     :style="backgroundStyle"
   >
-    <template v-if="showGridLines">
-      <GridLines />
-      <GridLines :gridSize="100" gridColor="rgba(100, 100, 100, 0.35)" />
-    </template>
+    <GridLines v-if="showGridLines" />
   </div>
 </template>
 

+ 19 - 31
src/views/Editor/Canvas/hooks/useDragElement.ts

@@ -29,7 +29,7 @@ export default (
     const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))
     const originActiveElementList = originElementList.filter(el => activeElementIdList.value.includes(el.id))
 
-    const sorptionRange = 3
+    const sorptionRange = 5
     const elOriginLeft = element.left
     const elOriginTop = element.top
     const elOriginWidth = element.width
@@ -211,25 +211,19 @@ export default (
         const min = Math.min(...range, targetMinX, targetMaxX)
         const max = Math.max(...range, targetMinX, targetMaxX)
         
-        if(Math.abs(targetMinY - value) < sorptionRange) {
-          if(!isHorizontalAdsorbed) {
-            targetTop = targetTop - (targetMinY - value)
-            isHorizontalAdsorbed = true
-          }
+        if(Math.abs(targetMinY - value) < sorptionRange && !isHorizontalAdsorbed) {
+          targetTop = targetTop - (targetMinY - value)
+          isHorizontalAdsorbed = true
           _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
         }
-        if(Math.abs(targetMaxY - value) < sorptionRange) {
-          if(!isHorizontalAdsorbed) {
-            targetTop = targetTop - (targetMaxY - value)
-            isHorizontalAdsorbed = true
-          }
+        if(Math.abs(targetMaxY - value) < sorptionRange && !isHorizontalAdsorbed) {
+          targetTop = targetTop - (targetMaxY - value)
+          isHorizontalAdsorbed = true
           _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
         }
-        if(Math.abs(targetCenterY - value) < sorptionRange) {
-          if(!isHorizontalAdsorbed) {
-            targetTop = targetTop - (targetCenterY - value)
-            isHorizontalAdsorbed = true
-          }
+        if(Math.abs(targetCenterY - value) < sorptionRange && !isHorizontalAdsorbed) {
+          targetTop = targetTop - (targetCenterY - value)
+          isHorizontalAdsorbed = true
           _alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
         }
       }
@@ -238,25 +232,19 @@ export default (
         const min = Math.min(...range, targetMinY, targetMaxY)
         const max = Math.max(...range, targetMinY, targetMaxY)
 
-        if(Math.abs(targetMinX - value) < sorptionRange) {
-          if(!isVerticalAdsorbed) {
-            targetLeft = targetLeft - (targetMinX - value)
-            isVerticalAdsorbed = true
-          }
+        if(Math.abs(targetMinX - value) < sorptionRange && !isVerticalAdsorbed) {
+          targetLeft = targetLeft - (targetMinX - value)
+          isVerticalAdsorbed = true
           _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
         }
-        if(Math.abs(targetMaxX - value) < sorptionRange) {
-          if(!isVerticalAdsorbed) {
-            targetLeft = targetLeft - (targetMaxX - value)
-            isVerticalAdsorbed = true
-          }
+        if(Math.abs(targetMaxX - value) < sorptionRange && !isVerticalAdsorbed) {
+          targetLeft = targetLeft - (targetMaxX - value)
+          isVerticalAdsorbed = true
           _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
         }
-        if(Math.abs(targetCenterX - value) < sorptionRange) {
-          if(!isVerticalAdsorbed) {
-            targetLeft = targetLeft - (targetCenterX - value)
-            isVerticalAdsorbed = true
-          }
+        if(Math.abs(targetCenterX - value) < sorptionRange && !isVerticalAdsorbed) {
+          targetLeft = targetLeft - (targetCenterX - value)
+          isVerticalAdsorbed = true
           _alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
         }
       }

+ 1 - 1
src/views/Editor/Canvas/hooks/useDragLineElement.ts

@@ -19,7 +19,7 @@ export default (elementList: Ref<PPTElement[]>) => {
   const dragLineElement = (e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => {
     let isMouseDown = true
 
-    const sorptionRange = 10
+    const sorptionRange = 8
 
     const startPageX = e.pageX
     const startPageY = e.pageY

+ 7 - 11
src/views/Editor/Canvas/hooks/useScaleElement.ts

@@ -175,7 +175,7 @@ export default (
     
     // 对齐吸附方法
     const alignedAdsorption = (currentX: number | null, currentY: number | null) => {
-      const sorptionRange = 3
+      const sorptionRange = 5
 
       const _alignmentLines: AlignmentLineProps[] = []
       let isVerticalAdsorbed = false
@@ -188,11 +188,9 @@ export default (
           const min = Math.min(...range, currentX || 0)
           const max = Math.max(...range, currentX || 0)
           
-          if(Math.abs(currentY - value) < sorptionRange) {
-            if(!isHorizontalAdsorbed) {
-              correctionVal.offsetY = currentY - value
-              isHorizontalAdsorbed = true
-            }
+          if(Math.abs(currentY - value) < sorptionRange && !isHorizontalAdsorbed) {
+            correctionVal.offsetY = currentY - value
+            isHorizontalAdsorbed = true
             _alignmentLines.push({ type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100 })
           }
         }
@@ -203,11 +201,9 @@ export default (
           const min = Math.min(...range, (currentY || 0))
           const max = Math.max(...range, (currentY || 0))
 
-          if(Math.abs(currentX - value) < sorptionRange) {
-            if(!isVerticalAdsorbed) {
-              correctionVal.offsetX = currentX - value
-              isVerticalAdsorbed = true
-            }
+          if(Math.abs(currentX - value) < sorptionRange && !isVerticalAdsorbed) {
+            correctionVal.offsetX = currentX - value
+            isVerticalAdsorbed = true
             _alignmentLines.push({ type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100 })
           }
         }