feat: add designBoard drag

This commit is contained in:
ShawnPhang 2024-04-02 14:47:54 +08:00
parent 79039c901f
commit 3da23d3642
13 changed files with 118 additions and 54 deletions

View File

@ -15,7 +15,7 @@
</head>
<body>
<div id="app"></div>
<div class="pointer-case" id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script defer src="/snap.svg-min.js"></script>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

View File

@ -7,17 +7,25 @@
}
body {
--el-color-primary: #2254f4;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
color: #333333;
font-family: Hiragino Sans GB, Hiragino Sans GB W3, Arial, Microsoft Yahei, STHeiti, sans-serif;
overflow: hidden;
}
.pointer-case {
cursor: -webkit-image-set(
url(data:image/png;base64,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)
2x
)
6 2,
default;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
color: #333333;
font-family: Hiragino Sans GB, Hiragino Sans GB W3, Arial, Microsoft Yahei, STHeiti, sans-serif;
overflow: hidden;
}
.move-case {
cursor: grab;
}
.move-case:active {
cursor: grabbing;
}
* {

View File

@ -1,10 +1,11 @@
import Selecto from 'selecto'
import Moveable, { getElementInfo } from 'moveable'
// import store from '@/store'
import { useWidgetStore } from '@/store'
import { useWidgetStore, useControlStore } from '@/store'
export default function(moveable: Moveable) {
const widgetStore = useWidgetStore()
const controlStore = useControlStore()
const selecto = new Selecto({
container: document.getElementById('page-design'),
selectableTargets: ['.layer'],
@ -45,5 +46,9 @@ export default function(moveable: Moveable) {
moveable.renderDirections = [] // ['nw', 'ne', 'sw', 'se'] // []
moveable.rotatable = false
moveable.target = [].slice.call(document.querySelectorAll('.widget-selected'))
}).on("dragStart", e => {
if (controlStore.dSpaceDown) {
e.stop();
}
})
}

View File

@ -105,7 +105,7 @@ const { pageDesignCanvasId } = defineProps<TProps>()
const { dPage } = storeToRefs(usePageStore())
const { dZoom, dPaddingTop, dScreen } = storeToRefs(canvasStore)
const { dDraging, showRotatable, dAltDown } = storeToRefs(controlStore)
const { dDraging, showRotatable, dAltDown, dSpaceDown } = storeToRefs(controlStore)
const { dWidgets, dActiveElement, dSelectWidgets, dHoverUuid } = storeToRefs(widgetStore)
@ -118,6 +118,32 @@ onMounted(() => {
if (!pageDesignEl) return
pageDesignEl.addEventListener('mousedown', handleSelection, false)
pageDesignEl.addEventListener('mousemove', debounce(100, false, handleMouseMove), false)
//
const scrollContainer: any = document.querySelector('#main')
const dragContainer: any = pageDesignEl
dragContainer.onmousedown = (e: any) => {
let mouseDownScrollPosition = {
scrollLeft: scrollContainer.scrollLeft,
scrollTop: scrollContainer.scrollTop,
}
let mouseDownPoint = {
x: e.clientX,
y: e.clientY,
}
dragContainer.onmousemove = (e: any) => {
if (!dSpaceDown.value) return
let dragMoveDiff = {
x: mouseDownPoint.x - e.clientX,
y: mouseDownPoint.y - e.clientY,
}
scrollContainer.scrollLeft = mouseDownScrollPosition.scrollLeft + dragMoveDiff.x
scrollContainer.scrollTop = mouseDownScrollPosition.scrollTop + dragMoveDiff.y
}
document.onmouseup = (e) => {
dragContainer.onmousemove = null
document.onmouseup = null
}
}
})
// components: {lineGuides},

View File

@ -1,7 +1,7 @@
<!--
* @Author: ShawnPhang
* @Date: 2022-04-08 10:31:34
* @Description:
* @Description: 标尺
* @LastEditors: ShawnPhang <https://m.palxp.cn>
* @LastEditTime: 2024-03-11 01:42:25
-->

View File

@ -81,8 +81,6 @@ watch(
realValue = calcZoom()
}
canvasStore.updateZoom(realValue)
// store.dispatch('updateZoom', realValue)
// updateZoom(realValue)
autoFixTop()
}
)
@ -155,8 +153,6 @@ function screenChange() {
//
if (activezoomIndex.value === zoomList.value.length - 1) {
canvasStore.updateZoom(calcZoom())
// store.dispatch('updateZoom', calcZoom())
// this.updateZoom(this.calcZoom())
autoFixTop()
}
}
@ -225,10 +221,9 @@ function mousewheelZoom(down: boolean) {
const value = Number(dZoom.value.toFixed(0))
if (down && value <= 1) return
canvasStore.updateZoom(down ? value - 1 : value + 1)
// store.dispatch('updateZoom', down ? value - 1 : value + 1)
// updateZoom(down ? value - 1 : value + 1)
zoom.value.text = (value + '%') as any
autoFixTop()
activezoomIndex.value = -99
}
function nearZoom(add?: boolean) {
@ -246,7 +241,6 @@ function nearZoom(add?: boolean) {
function calcZoom() {
let widthZoom = ((dScreen.value.width - 142) * 100) / dPage.value.width
let heightZoom = ((dScreen.value.height - 122) * 100) / dPage.value.height
bestZoom.value = Math.min(widthZoom, heightZoom)
return bestZoom.value
}

View File

@ -93,7 +93,6 @@ const targetRef = ref<HTMLImageElement | null>(null)
let rotateTemp: number | null = null
let flipTemp: string | null = null
let locksTemp: boolean[] | null = null
// const {
// dActiveElement, dWidgets, dMouseXY, dDropOverUuid, dCropUuid
@ -129,7 +128,7 @@ watch(
el?.removeEventListener('mousedown', touchstart, false)
}
fixRotate()
lockOthers()
lockOthers(val)
}
)
@ -314,21 +313,15 @@ function fixRotate() {
}, 100)
}
function lockOthers() {
function lockOthers(isCrop) {
//
if (locksTemp && locksTemp.length > 0) {
for (let i = 0; i < locksTemp.length; i++) {
dWidgets.value[i].lock = locksTemp[i]
}
locksTemp = []
} else {
locksTemp = []
widgetStore.lockWidgets()
if (!isCrop) return
for (const widget of dWidgets.value) {
locksTemp.push(widget?.lock || false)
if (widget.uuid === props.params.uuid) {
widget.lock = false
break;
}
dWidgets.value.forEach((widget: any) => {
widget.uuid != props.params.uuid && (widget.lock = true)
})
}
}
// cropDone(e) {

View File

@ -334,10 +334,7 @@ function imgCrop(val: boolean) {
const { left, top } = el.getBoundingClientRect()
toolBarStyle = { left: left + 'px', top: top + 'px' }
state.innerElement.cropEdit = val
// store.commit('setShowRotatable', !val)
controlStore.setShowRotatable(!val)
}

View File

@ -7,13 +7,13 @@
*/
import { useControlStore, useWidgetStore } from '@/store'
import { TdWidgetData } from '@/store/design/widget'
// import store from '@/store'
export default function keyCodeOptions(e: any, params: any) {
const { f } = params
const appContainer: any = document.querySelector('#app')
const controlStore = useControlStore()
const widgetStore = useWidgetStore()
export default function keyCodeOptions(e: any, params: any) {
const { f } = params
switch (e.keyCode) {
case 38:
udlr('top', -1 * f, e)
@ -49,6 +49,10 @@ export default function keyCodeOptions(e: any, params: any) {
}
break
}
if (e.key === ' ') {
dealWithSpace(e)
}
}
/**
*
@ -81,15 +85,18 @@ function udlr(type: keyof TdWidgetData, value: any, event: any) {
key: type,
value: result,
})
// store.dispatch('updateWidgetData', {
// uuid: store.getters.dActiveElement.uuid,
// key: type,
// value: result,
// })
}
}
// TODO: 键盘移位需要防抖入栈
// timer = setTimeout(() => {
// this.pushHistory()
// }, 100)
function dealWithSpace(event: any) {
const widgetStore: any = useWidgetStore()
// 防止编辑文字时空格按不出来
if (!widgetStore.dActiveElement.editable) {
event.preventDefault()
appContainer.classList.add('move-case');
if (!controlStore.dSpaceDown) {
widgetStore.lockWidgets()
}
controlStore.setSpaceDown(true)
}
}

View File

@ -12,6 +12,7 @@
import keyCodeOptions from './methods/keyCodeOptions'
import dealWithCtrl from './methods/dealWithCtrl'
import { TControlStore } from '@/store/design/control'
import { useControlStore, useWidgetStore } from '@/store'
const ignoreNode = ['INPUT', 'TEXTAREA']
@ -31,6 +32,9 @@ const systemKeyCode = [
]
let hadDown = false
const appContainer: any = document.querySelector('#app')
const controlStore = useControlStore()
const widgetStore = useWidgetStore()
const shortcuts = {
methods: {
@ -118,18 +122,20 @@ const shortcuts = {
},
handleKeyup(store: TControlStore, checkCtrl: number | undefined) {
return (e: any) => {
console.log(e)
clearInterval(checkCtrl)
hadDown = false
if (e.key === 'Alt' || e.key === 'Shift' || e.key === 'Control' || e.key === 'Meta') {
store.updateAltDown(false)
// store.dispatch('updateAltDown', false)
}
if (e.key === ' ') {
appContainer.classList.remove('move-case');
controlStore.setSpaceDown(false)
widgetStore.lockWidgets()
}
}
},
dealCtrl(e: any, instance: any) {
dealWithCtrl(e, instance)
console.log(e.key, e.keyCode)
},
},
}

View File

@ -25,7 +25,9 @@ type TControlState = {
showRotatable: boolean
/** 记录是否按下alt键 / 或ctrl */
dAltDown: boolean
/** 正在编辑or裁剪的组件id */
// 是否按下空格键
dSpaceDown: boolean
/** orid *
dCropUuid: string
}
@ -43,6 +45,7 @@ type TControlAction = {
stopDMove: () => void
/** 设置正在裁剪or编辑的组件 */
setCropUuid: (uuid: string) => void
setSpaceDown: (uuid: boolean) => void // 设置是否按下空格键
}
/** 全局控制配置 */
@ -56,6 +59,7 @@ const ControlStore = defineStore<"controlStore", TControlState, {}, TControlAct
showRotatable: true, // 是否显示moveable的旋转按钮
dAltDown: false, // 记录是否按下alt键 / 或ctrl
dCropUuid: '-1', // 正在编辑or裁剪的组件id
dSpaceDown: false, // 记录是否按下空格键
}),
getters: {},
actions: {
@ -108,6 +112,9 @@ const ControlStore = defineStore<"controlStore", TControlState, {}, TControlAct
// 设置正在裁剪or编辑的组件
this.dCropUuid = uuid
},
setSpaceDown(val: boolean) {
this.dSpaceDown = val
}
}
})

View File

@ -235,3 +235,22 @@ export function setWidgetStyle(state: TWidgetStore, { uuid, key, value, pushHist
export function setDWidgets(state: TWidgetStore, e: TdWidgetData[]) {
state.dWidgets = e
}
// 锁定所有图层 / 再次调用时还原图层
let lastLocks: boolean[] | null = null
export function lockWidgets(state: TWidgetStore) {
if (lastLocks && lastLocks.length > 0) {
for (let i = 0; i < lastLocks.length; i++) {
state.dWidgets[i].lock = lastLocks[i]
}
lastLocks = []
} else {
lastLocks = []
for (const widget of state.dWidgets) {
lastLocks.push(widget?.lock || false)
}
state.dWidgets.forEach((widget: any) => {
widget.lock = true
})
}
}

View File

@ -10,7 +10,7 @@ import { Store, defineStore } from "pinia";
import { TInidDMovePayload, TMovePayload, dMove, initDMove, setDropOver, setMouseEvent, setdActiveElement, updateGroupSize, updateHoverUuid } from "./actions";
import { TPageState } from "../page";
import { TInitResize, TResize, TdResizePayload, dResize, initDResize, resize } from "./actions/resize";
import { TUpdateWidgetMultiplePayload, TUpdateWidgetPayload, TsetWidgetStyleData, addWidget, deleteWidget, setDWidgets, setWidgetStyle, updateWidgetData, updateWidgetMultiple } from "./actions/widget";
import { TUpdateWidgetMultiplePayload, TUpdateWidgetPayload, TsetWidgetStyleData, addWidget, deleteWidget, setDWidgets, setWidgetStyle, updateWidgetData, updateWidgetMultiple, lockWidgets } from "./actions/widget";
import { addGroup } from "./actions/group";
import { setTemplate } from "./actions/template";
import { copyWidget, pasteWidget } from "./actions/clone";
@ -116,6 +116,7 @@ type TAction = {
resize: (data: TResize) => void
setWidgetStyle: (data: TsetWidgetStyleData) => void
setDWidgets: (data: TdWidgetData[]) => void
lockWidgets: () => void
setMouseEvent: (e: MouseEvent | null) => void
setdActiveElement: (data: TdWidgetData) => void
}
@ -176,6 +177,7 @@ const WidgetStore = defineStore<"widgetStore", TWidgetState, TGetter, TAction>("
resize(data) { resize(this, data) },
setWidgetStyle(data) { setWidgetStyle(this, data) },
setDWidgets(data) { setDWidgets(this, data) },
lockWidgets() { lockWidgets(this) },
setMouseEvent(event) { setMouseEvent(this, event) },
setdActiveElement(data) { setdActiveElement(this, data) },
}