mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-28 04:10:31 +08:00
feat: add designBoard drag
This commit is contained in:
parent
79039c901f
commit
3da23d3642
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -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();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
-->
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -25,7 +25,9 @@ type TControlState = {
|
||||
showRotatable: boolean
|
||||
/** 记录是否按下alt键 / 或ctrl */
|
||||
dAltDown: boolean
|
||||
/** 正在编辑or裁剪的组件id */
|
||||
// 是否按下空格键
|
||||
dSpaceDown: boolean
|
||||
/** 正在编辑or裁剪的组件id *
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
@ -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) },
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user