jeo young 2 rokov pred
rodič
commit
f64cd4dcf1

+ 2 - 1
src/enums/editPageEnum.ts

@@ -67,7 +67,8 @@ export enum WinKeyboard {
   ALT = ' alt',
   CTRL_SOURCE_KEY = 'control',
   SHIFT_SOURCE_KEY = 'shift',
-  ALT_SOURCE_KEY = 'alt'
+  ALT_SOURCE_KEY = 'alt',
+  SPACE = 'Space'
 }
 
 // Mac 键盘枚举

+ 7 - 1
src/utils/utils.ts

@@ -273,15 +273,21 @@ export const objToCookie = (obj: RequestParamsObjType) => {
  * @returns
  */
 export const setKeyboardDressShow = (keyCode?: number) => {
-  const code = new Map([[17, WinKeyboard.CTRL]])
+  const code = new Map([
+    [17, WinKeyboard.CTRL],
+    [32, WinKeyboard.SPACE]
+  ])
 
   const dom = document.getElementById('keyboard-dress-show')
   if (!dom) return
   if (!keyCode) {
+    window.onKeySpacePressHold?.(false)
     dom.innerText = ''
     return
   }
   if (keyCode && code.has(keyCode)) {
+    window.onKeySpacePressHold?.(true)
     dom.innerText = `按下了「${code.get(keyCode)}」键`
   }
 }
+

+ 27 - 9
src/views/chart/ContentBox/index.vue

@@ -18,14 +18,14 @@
       </n-space>
     </div>
 
-    <div
-      class="content"
-      :class="{
-        'content-height-show-top-bottom': showBottom || showTop,
-        'content-height-show-both': showBottom && showTop
-      }"
-    >
-      <template v-if="xScroll">
+    <div class="content" :class="{
+      'content-height-show-top-bottom': showBottom || showTop,
+      'content-height-show-both': showBottom && showTop
+    }">
+      <template v-if="disabledScroll">
+        <slot></slot>
+      </template>
+      <template v-else-if="xScroll">
         <n-scrollbar x-scrollable>
           <n-scrollbar>
             <slot></slot>
@@ -83,7 +83,11 @@ defineProps({
   xScroll: {
     type: Boolean,
     default: false
-  }
+  },
+  disabledScroll: {
+    type: Boolean,
+    default: false
+  },
 })
 
 const backHandle = () => {
@@ -93,41 +97,52 @@ const backHandle = () => {
 
 <style lang="scss" scoped>
 $topOrBottomHeight: 40px;
+
 @include go(content-box) {
   height: calc(100vh - #{$--header-height});
   margin: 1px;
   margin-bottom: 0;
+
   &.bg-depth0 {
     @include fetch-bg-color('background-color1');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color1');
     }
   }
+
   &.bg-depth1 {
     @include fetch-bg-color('background-color1');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color2');
     }
   }
+
   &.bg-depth2 {
     @include fetch-bg-color('background-color2');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color3');
     }
   }
+
   &.bg-depth3 {
     @include fetch-bg-color('background-color3');
+
     .bottom,
     .top {
       @include fetch-bg-color('background-color4');
     }
   }
+
   &.flex {
     flex: 1;
   }
+
   .top,
   .bottom {
     display: flex;
@@ -138,10 +153,12 @@ $topOrBottomHeight: 40px;
     padding: 0 10px;
     border-top: 1px solid;
     @include fetch-border-color('hover-border-color');
+
     .mt-1 {
       margin-top: 2px;
     }
   }
+
   .top {
     border-bottom: 1px solid;
     @include fetch-border-color('background-color1');
@@ -159,6 +176,7 @@ $topOrBottomHeight: 40px;
   .content-height-show-top-bottom {
     height: calc(100vh - #{$--header-height} - #{$topOrBottomHeight});
   }
+
   .content-height-show-both {
     height: calc(100vh - #{$--header-height} - #{$topOrBottomHeight} - #{$topOrBottomHeight});
   }

+ 193 - 0
src/views/chart/ContentEdit/components/EditRule/ruler.vue

@@ -0,0 +1,193 @@
+<template>
+    <div :style="{ position: 'relative', overflow: 'hidden', width: '100%', height: '100%' }">
+        <sketch-rule :thick="thick" :scale="scale" :width="canvasBox().width" :height="canvasBox().height"
+            :startX="startX" :startY="startY" :lines="lines"
+            :palette="{ bgColor: '#18181c', longfgColor: '#4d4d4d', shortfgColor: '#4d4d4d', fontColor: '#4d4d4d', shadowColor: '#18181c', borderColor: '#18181c', cornerActiveColor: '#18181c' }">
+        </sketch-rule>
+        <div ref="$app" class="screens" @scroll="handleScroll">
+            <div ref="$container" class="screenContainer" :style="{ width: screenContainerWidth + 'px' }">
+                <div id="refcanvasBox" ref="refcanvasBox" class="canvas" @mousedown="dragCanvas"
+                    :style="{ marginLeft: '-' + (canvasBox().width / 2 - 25) + 'px' }">
+                    <div :style="{ pointerEvents: isPressSpace ? 'none' : 'auto' }">
+                        <slot></slot>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script setup lang="ts">
+import { ref, reactive, onMounted, toRefs, watch, onUnmounted, computed } from 'vue'
+import { listen } from "dom-helpers"
+
+import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
+
+const chartEditStore = useChartEditStore()
+
+const thick = 20
+const screenContainerWidth = 5000
+var prevMoveXVallue = [0, 0]
+var prevMoveYVallue = [0, 0]
+
+const $app = ref()
+const refcanvasBox = ref()
+const $container = ref()
+
+const scale = computed(() => {
+    return chartEditStore.getEditCanvas.scale
+})
+const startX = ref(0)
+const startY = ref(0)
+const lines = reactive({ h: [], v: [] })
+
+const handleWheel = (e: any) => {
+    e.preventDefault()
+    if (e.ctrlKey || e.metaKey) {
+        // const nextScale = parseFloat(Math.max(.2, scale.value - e.deltaY / canvasBox().height).toFixed(2))
+        // chartEditStore.setScale(nextScale)
+
+        chartEditStore.setScale(e.wheelDelta >= 120 ? scale.value + 0.01 : e.wheelDelta <= 120 ? scale.value - 0.01 : scale.value)
+    }
+}
+
+const isPressSpace = ref(false)
+const cursorStyle = ref('auto')
+
+window.onKeySpacePressHold = (isHold: boolean) => {
+    isPressSpace.value = isHold
+}
+watch(
+    () => isPressSpace.value,
+    newValue => {
+        cursorStyle.value = newValue ? 'grab' : 'auto'
+    }
+)
+
+onMounted(() => {
+    $app.value.addEventListener('wheel', handleWheel, { passive: false })
+    // 滚动居中
+    $app.value.scrollLeft = $container.value.getBoundingClientRect().width / 2 - canvasBox().width / 2
+
+})
+
+const handleScroll = () => {
+    const screensRect = $app.value.getBoundingClientRect()
+    const canvasRect = refcanvasBox.value.getBoundingClientRect()
+
+    // 标尺开始的刻度
+    startX.value = (screensRect.left + thick - canvasRect.left) / scale.value
+    startY.value = (screensRect.top + thick - canvasRect.top) / scale.value
+}
+// 处理标尺重制大小
+watch(
+    () => scale.value,
+    (newValue, oldValue) => {
+        if (oldValue !== newValue) {
+            handleScroll()
+            chartEditStore.setScale(newValue)
+        }
+    }
+)
+
+onUnmounted(() => {
+    $app.value.removeEventListener('wheel', handleWheel)
+})
+
+const dragCanvas = (e: any) => {
+    if (!window.$KeyboardActive?.space) return
+
+    // @ts-ignore
+    document.activeElement?.blur()
+
+    e.preventDefault()
+    e.stopPropagation()
+
+    const startX = e.pageX
+    const startY = e.pageY
+
+    const un1 = listen(window, "mousemove", (e: any) => {
+
+        const nx = e.pageX - startX
+        const ny = e.pageY - startY
+
+        const [prevMoveX1, prevMoveX2] = prevMoveXVallue
+        const [prevMoveY1, prevMoveY2] = prevMoveYVallue
+
+        prevMoveXVallue = [prevMoveX2, nx]
+        prevMoveYVallue = [prevMoveY2, ny]
+
+        $app.value.scrollLeft -= prevMoveX2 > prevMoveX1 ? Math.abs(prevMoveX2 - prevMoveX1) : -Math.abs(prevMoveX2 - prevMoveX1)
+        $app.value.scrollTop -= prevMoveY2 > prevMoveY1 ? Math.abs(prevMoveY2 - prevMoveY1) : -Math.abs(prevMoveY2 - prevMoveY1)
+    })
+    const un2 = listen(window, "mouseup", () => {
+        un1()
+        un2()
+        prevMoveXVallue = [0, 0]
+        prevMoveYVallue = [0, 0]
+    })
+}
+
+const { width, height } = toRefs(chartEditStore.getEditCanvasConfig)
+
+const canvasBox = () => {
+    const layoutDom = document.getElementById('go-chart-edit-layout')
+    if (layoutDom) {
+        return {
+            height: layoutDom.clientHeight - 40 - 44,
+            width: layoutDom.clientWidth
+        }
+    }
+    return {
+        width: width.value,
+        height: height.value
+    }
+}
+</script>
+<style lang="scss" scoped>
+.screens {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    overflow: auto;
+    user-select: none;
+
+    /* firefox */
+    scrollbar-color: rgba(144, 146, 152, .3) transparent;
+    scrollbar-width: thin;
+
+    /* chrome */
+    &::-webkit-scrollbar,
+    &::-webkit-scrollbar-track-piece {
+        background-color: transparent;
+    }
+
+    &::-webkit-scrollbar {
+        width: 7px;
+    }
+
+    &::-webkit-scrollbar-thumb {
+        border-radius: 5px;
+        background-color: rgba(144, 146, 152, .3);
+    }
+}
+
+.screenContainer {
+    position: absolute;
+    height: 3000px;
+}
+
+.canvas {
+    position: absolute;
+    top: 80px;
+    left: 50%;
+    transform-origin: 50% 0;
+
+    &:hover {
+        cursor: v-bind('cursorStyle');
+    }
+
+    &:active {
+        cursor: crosshair;
+    }
+}
+</style>

+ 38 - 63
src/views/chart/ContentEdit/index.vue

@@ -1,71 +1,43 @@
 <template>
-  <edit-rule></edit-rule>
-  <content-box
-    id="go-chart-edit-layout"
-    :flex="true"
-    :showTop="false"
-    :showBottom="true"
-    :depth="1"
-    :xScroll="true"
-    @mousedown="mousedownHandleUnStop"
-    @drop="dragHandle"
-    @dragover="dragoverHandle"
-    @dragenter="dragoverHandle"
-  >
-    <!-- 画布主体 -->
-    <div id="go-chart-edit-content" @contextmenu="handleContextMenu">
-      <!-- 展示 -->
-      <edit-range>
-        <!-- 滤镜预览 -->
-        <div
-          :style="{
+  <!-- <edit-rule></edit-rule> -->
+  <content-box id="go-chart-edit-layout" :flex="true" :showTop="false" :showBottom="true" :depth="1" :xScroll="true" :disabledScroll="true"
+    @mousedown="mousedownHandleUnStop" @drop="dragHandle" @dragover="dragoverHandle" @dragenter="dragoverHandle">
+    <ruler>
+      <!-- 画布主体 -->
+      <div id="go-chart-edit-content" @contextmenu="handleContextMenu">
+        <!-- 展示 -->
+        <edit-range>
+          <!-- 滤镜预览 -->
+          <div :style="{
             ...getFilterStyle(chartEditStore.getEditCanvasConfig),
             ...rangeStyle
-          }"
-        >
-          <!-- 图表 -->
-          <div v-for="(item, index) in chartEditStore.getComponentList" :key="item.id">
-            <!-- 分组 -->
-            <edit-group
-              v-if="item.isGroup"
-              :groupData="(item as CreateComponentGroupType)"
-              :groupIndex="index"
-            ></edit-group>
-
-            <!-- 单组件 -->
-            <edit-shape-box
-              v-else
-              :data-id="item.id"
-              :index="index"
-              :style="{
+          }">
+            <!-- 图表 -->
+            <div v-for="(item, index) in chartEditStore.getComponentList" :key="item.id">
+              <!-- 分组 -->
+              <edit-group v-if="item.isGroup" :groupData="(item as CreateComponentGroupType)"
+                :groupIndex="index"></edit-group>
+
+              <!-- 单组件 -->
+              <edit-shape-box v-else :data-id="item.id" :index="index" :style="{
                 ...useComponentStyle(item.attr, index),
                 ...getBlendModeStyle(item.styles) as any
-              }"
-              :item="item"
-              @click="mouseClickHandle($event, item)"
-              @mousedown="mousedownHandle($event, item)"
-              @mouseenter="mouseenterHandle($event, item)"
-              @mouseleave="mouseleaveHandle($event, item)"
-              @contextmenu="handleContextMenu($event, item, optionsHandle)"
-            >
-              <component
-                class="edit-content-chart"
-                :class="animationsClass(item.styles.animations)"
-                :is="item.chartConfig.chartKey"
-                :chartConfig="item"
-                :themeSetting="themeSetting"
-                :themeColor="themeColor"
-                :style="{
-                  ...useSizeStyle(item.attr),
-                  ...getFilterStyle(item.styles),
-                  ...getTransformStyle(item.styles)
-                }"
-              ></component>
-            </edit-shape-box>
+              }" :item="item" @click="mouseClickHandle($event, item)" @mousedown="mousedownHandle($event, item)"
+                @mouseenter="mouseenterHandle($event, item)" @mouseleave="mouseleaveHandle($event, item)"
+                @contextmenu="handleContextMenu($event, item, optionsHandle)">
+                <component class="edit-content-chart" :class="animationsClass(item.styles.animations)"
+                  :is="item.chartConfig.chartKey" :chartConfig="item" :themeSetting="themeSetting"
+                  :themeColor="themeColor" :style="{
+                    ...useSizeStyle(item.attr),
+                    ...getFilterStyle(item.styles),
+                    ...getTransformStyle(item.styles)
+                  }"></component>
+              </edit-shape-box>
+            </div>
           </div>
-        </div>
-      </edit-range>
-    </div>
+        </edit-range>
+      </div>
+    </ruler>
 
     <!-- 工具栏 -->
     <template #aside>
@@ -97,7 +69,8 @@ import { useComponentStyle, useSizeStyle } from './hooks/useStyle.hook'
 import { ContentBox } from '../ContentBox/index'
 import { EditGroup } from './components/EditGroup'
 import { EditRange } from './components/EditRange'
-import { EditRule } from './components/EditRule'
+// import { EditRule } from './components/EditRule'
+import Ruler from './components/EditRule/ruler.vue'
 import { EditBottom } from './components/EditBottom'
 import { EditShapeBox } from './components/EditShapeBox'
 import { EditTools } from './components/EditTools'
@@ -185,12 +158,14 @@ onMounted(() => {
   overflow: hidden;
   @extend .go-point-bg;
   @include background-image('background-point');
+
   @include goId('chart-edit-content') {
     border-radius: 10px;
     margin: 25px;
     overflow: hidden;
     @extend .go-transition;
     @include fetch-theme('box-shadow');
+
     .edit-content-chart {
       position: absolute;
       overflow: hidden;

+ 19 - 7
src/views/chart/hooks/useKeyboard.hook.ts

@@ -110,21 +110,33 @@ const macKeyList: Array<string> = [
 const keyRecordHandle = () => {
   // 默认赋值
   window.$KeyboardActive = {
-    ctrl: false
+    ctrl: false,
+    space: false
   }
-  
+
   document.onkeydown = (e: KeyboardEvent) => {
-    if(e.keyCode === 17 && window.$KeyboardActive) {
+    const { keyCode } = e
+    if (keyCode == 32 && e.target == document.body) e.preventDefault()
+
+    if ([17, 32].includes(keyCode) && window.$KeyboardActive) {
       setKeyboardDressShow(e.keyCode)
-      window.$KeyboardActive.ctrl = true
+      switch (keyCode) {
+        case 17: window.$KeyboardActive.ctrl = true; break
+        case 32: window.$KeyboardActive.space = true; break
+      }
     }
   }
 
   document.onkeyup = (e: KeyboardEvent) => {
-    if(e.keyCode === 17 && window.$KeyboardActive) 
-    {
-      window.$KeyboardActive.ctrl = false
+    const { keyCode } = e
+    if (keyCode == 32 && e.target == document.body) e.preventDefault()
+
+    if ([17, 32].includes(keyCode) && window.$KeyboardActive) {
       setKeyboardDressShow()
+      switch (keyCode) {
+        case 17: window.$KeyboardActive.ctrl = false; break
+        case 32: window.$KeyboardActive.space = false; break
+      }
     }
   }
 }

+ 2 - 0
types/global.d.ts

@@ -7,6 +7,8 @@ interface Window {
   $vue: any
   // 键盘按键记录
   $KeyboardActive?: { [T: string]: boolean }
+  onKeySpacePressHold?: Function
+
   // 编辑 JSON 的存储对象
   opener: any
 }

+ 2 - 1
types/shims-vue.d.ts

@@ -4,4 +4,5 @@ declare module '*.vue' {
   export default component
 }
 
-declare module 'lodash/*'
+declare module 'lodash/*'
+declare module 'dom-helpers'