Skip to content

Commit c53fbde

Browse files
committed
fix: 重构画布坐标系
1 parent 60de1df commit c53fbde

File tree

7 files changed

+67
-78
lines changed

7 files changed

+67
-78
lines changed

packages/canvas/src/components/container/CanvasAction.vue

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ import {
117117
IconEyeclose
118118
} from '@opentiny/vue-icon'
119119
import {
120+
canvasState,
120121
getCurrent,
121122
removeNodeById,
122123
selectNode,
@@ -379,15 +380,14 @@ export default {
379380
}
380381
}
381382
382-
const getStyleValues = (selectState, siteCanvasWidth, siteCanvasHeight) => {
383+
const getStyleValues = (selectState, canvasSize, labelWidth, optionWidth) => {
383384
const { left, top, width, height, doc } = selectState
384-
const labelRect = labelRef.value.getBoundingClientRect()
385-
const optionRect = optionRef.value.getBoundingClientRect()
385+
const { width: canvasWidth, height: canvasHeight } = canvasSize
386386
// 标签宽度和工具操作条宽度之和加上间距
387-
const fullRectWidth = labelRect.width + optionRect.width + OPTION_SPACE
387+
const fullRectWidth = labelWidth + optionWidth + OPTION_SPACE
388388
389389
// 是否 将label 标签放置到底部,判断 top 距离
390-
const isLabelAtBottom = top <= LABEL_HEIGHT
390+
const isLabelAtBottom = top < LABEL_HEIGHT
391391
const labelAlign = new Align({
392392
alignLeft: true,
393393
horizontalValue: 0,
@@ -396,7 +396,7 @@ export default {
396396
})
397397
398398
// 是否将操作栏放置到底部,判断当前选中组件底部与页面底部的距离。
399-
const isOptionAtBottom = siteCanvasHeight - top - height > OPTION_BAR_HEIGHT
399+
const isOptionAtBottom = canvasHeight - top - height >= OPTION_BAR_HEIGHT
400400
const optionAlign = new Align({
401401
alignLeft: false,
402402
horizontalValue: 0,
@@ -410,39 +410,39 @@ export default {
410410
// 选中框宽度小于标签宽度和工具操作条宽度之和加上间距
411411
412412
// 如果labe宽度大于选中框宽度,并且label右侧已经超出画布,则label对齐右侧
413-
const isLabelAlignRight = labelRect.width > width && left + labelRect.width + scrollBarWidth > siteCanvasWidth
413+
const isLabelAlignRight = labelWidth > width && left + labelWidth + scrollBarWidth > canvasWidth
414414
if (isLabelAlignRight) {
415415
labelAlign.align(positions.RIGHT)
416416
}
417417
418418
// 如果option宽度大于选中框宽度,并且option左侧已经超出画布,则option对齐左侧
419-
const isOptionAlignLeft = optionRect.width > width && left + width - optionRect.width < 0
419+
const isOptionAlignLeft = optionWidth > width && left + width - optionWidth < 0
420420
if (isOptionAlignLeft) {
421421
optionAlign.align(positions.LEFT)
422422
}
423423
424424
if (isLabelAtBottom === isOptionAtBottom) {
425425
// 标签框和工具操作框都在顶部或者都在底部
426426
427-
if (left + fullRectWidth < siteCanvasWidth) {
427+
if (left + fullRectWidth < canvasWidth) {
428428
// 都放在左侧
429429
labelAlign.align(positions.LEFT)
430-
optionAlign.align(positions.LEFT, labelRect.width + OPTION_SPACE)
430+
optionAlign.align(positions.LEFT, labelWidth + OPTION_SPACE)
431431
} else {
432432
// 都放在右侧
433433
optionAlign.align(positions.RIGHT)
434-
labelAlign.align(positions.RIGHT, optionRect.width + OPTION_SPACE)
434+
labelAlign.align(positions.RIGHT, optionWidth + OPTION_SPACE)
435435
}
436436
}
437437
} else {
438438
if (left < 0) {
439439
labelAlign.align(positions.LEFT, Math.min(-left, width - fullRectWidth))
440440
}
441441
442-
if (left + width + scrollBarWidth > siteCanvasWidth) {
442+
if (left + width + scrollBarWidth > canvasWidth) {
443443
optionAlign.align(
444444
positions.RIGHT,
445-
Math.min(left + width + scrollBarWidth - siteCanvasWidth, width - fullRectWidth)
445+
Math.min(left + width + scrollBarWidth - canvasWidth, width - fullRectWidth)
446446
)
447447
}
448448
}
@@ -454,8 +454,7 @@ export default {
454454
}
455455
456456
watchPostEffect(async () => {
457-
let { left } = props.selectState
458-
const { top, width, height, doc } = props.selectState
457+
const { left, top, width, height, doc } = props.selectState
459458
460459
// nextTick后ref才能获取到元素。需要把监听的依赖放在await之前,否则无法监听变化
461460
await nextTick()
@@ -470,15 +469,17 @@ export default {
470469
return
471470
}
472471
473-
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
474472
const scale = useLayout().getScale()
473+
const canvasRect = canvasState.iframe.getBoundingClientRect()
474+
const { width: labelWidth } = labelRef.value.getBoundingClientRect()
475+
const { width: optionWidth } = optionRef.value.getBoundingClientRect()
475476
476-
left -= ((1 - scale) / 2) * siteCanvasRect.width
477-
477+
// canvas容器中,iframe以及iframe之外的元素clientRect的尺寸都是缩放过的,除以scale得到原始大小
478478
const { labelStyleValue, optionStyleValue } = getStyleValues(
479479
{ left, top, width, height, doc },
480-
siteCanvasRect.width * scale,
481-
siteCanvasRect.height
480+
{ width: canvasRect.width / scale, height: canvasRect.height / scale },
481+
labelWidth / scale,
482+
optionWidth / scale
482483
)
483484
484485
labelStyle.value = labelStyleValue

packages/canvas/src/components/container/CanvasContainer.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ import {
5050
updateRect,
5151
getElement,
5252
dragStart,
53-
getOffset,
5453
selectNode,
5554
initCanvas,
5655
clearLineState,
@@ -100,7 +99,7 @@ export default {
10099
101100
// 如果是点击右键则打开右键菜单
102101
if (event.button === 2) {
103-
openMenu(getOffset(event.target), event)
102+
openMenu(event)
104103
}
105104
}
106105
}

packages/canvas/src/components/container/CanvasMenu.vue

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,11 @@ export const closeMenu = () => {
5151
current.value = null
5252
}
5353
54-
export const openMenu = (offset, event) => {
55-
const { x, y } = offset
56-
const { getScale } = useLayout()
54+
export const openMenu = (event) => {
5755
menuState.position = {
5856
// 位置处于画布右侧边缘时需要调整显示方向 TODO
59-
left: event.clientX * getScale() + x + 2 + 'px',
60-
top: event.clientY * getScale() + y + 'px'
57+
left: event.clientX + 2 + 'px',
58+
top: event.clientY + 'px'
6159
}
6260
menuState.show = sessionStorage.getItem('pageInfo') ? true : false
6361
@@ -235,7 +233,7 @@ export default {
235233

236234
<style lang="less" scoped>
237235
.context-menu {
238-
position: fixed;
236+
position: absolute;
239237
z-index: 10;
240238
}
241239
.menu-item {

packages/canvas/src/components/container/CanvasResize.vue

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ import { canvasState } from './container'
1717
export default {
1818
setup() {
1919
const sizeStyle = computed(() => {
20-
const { width, maxWidth, minWidth, scale } = useLayout().getDimension()
20+
const { width, height, maxWidth, minWidth } = useLayout().getDimension()
2121
return {
2222
width,
23+
height,
2324
maxWidth,
24-
minWidth,
25-
height: `${100 / scale}%`,
26-
transform: `scale(${scale}) translateY(-${(100 / scale - 100) / 2}%)`
25+
minWidth
2726
}
2827
})
2928

packages/canvas/src/components/container/CanvasResizeBorder.vue

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,17 @@ export default {
3939
}
4040
4141
const handleResize = (event, type) => {
42-
let { clientX, clientY } = event
42+
if (!props.iframe) {
43+
return
44+
}
4345
44-
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
46+
let { clientX, clientY } = event
47+
const iframeRect = props.iframe.getBoundingClientRect()
4548
const scale = useLayout().getScale()
46-
const offsetX = ((1 - scale) / 2) * siteCanvasRect.width
47-
48-
if (type === 'iframe' && props.iframe) {
49-
clientX = clientX - offsetX
50-
} else {
51-
clientX = clientX - siteCanvasRect.left - offsetX
52-
clientY = clientY - siteCanvasRect.top
5349
54-
if (scale < 1) {
55-
clientX = clientX / scale - offsetX
56-
clientY = clientY / scale
57-
}
50+
if (type !== 'iframe') {
51+
clientX = (clientX - iframeRect.left) / scale
52+
clientY = (clientY - iframeRect.top) / scale
5853
}
5954
6055
const { parent, schema } = getCurrent()
@@ -76,14 +71,9 @@ export default {
7671
const parentWidth = parseInt(window.getComputedStyle(parentDomNode).width, 10)
7772
7873
// 最大宽度不能大于父组件宽度
79-
if (newWidth >= parentWidth) {
80-
newWidth = parentWidth
81-
}
82-
74+
newWidth = Math.min(newWidth, parentWidth)
8375
// 最小宽度32
84-
if (newWidth <= 32) {
85-
newWidth = 32
86-
}
76+
newWidth = Math.max(newWidth, 32)
8777
8878
schema.props.flexBasis = `${newWidth}px`
8979
schema.props.widthType = 'fixed'

packages/canvas/src/components/container/container.js

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -346,16 +346,13 @@ const setSelectRect = (element) => {
346346
element = element || getDocument().body
347347

348348
const { left, height, top, width } = getRect(element)
349-
const { x, y } = getOffset(element)
350-
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
351349
const componentName = getCurrent().schema?.componentName || ''
352-
const scale = useLayout().getScale()
353350
clearHover()
354351
Object.assign(selectState, {
355-
width: width * scale,
356-
height: height * scale,
357-
top: top * scale + y - siteCanvasRect.y,
358-
left: left * scale + x - siteCanvasRect.x,
352+
width,
353+
height,
354+
top,
355+
left,
359356
componentName,
360357
doc: getDocument()
361358
})
@@ -479,9 +476,6 @@ const setHoverRect = (element, data) => {
479476
const configure = getConfigure(componentName)
480477
const rect = getRect(element)
481478
const { left, height, top, width } = rect
482-
const { x, y } = getOffset(element)
483-
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
484-
const scale = useLayout().getScale()
485479

486480
hoverState.configure = configure
487481

@@ -510,23 +504,22 @@ const setHoverRect = (element, data) => {
510504
if (childEle) {
511505
const childRect = getRect(childEle)
512506
const { left, height, top, width } = childRect
513-
const { x, y } = getOffset(childEle)
514507
const posLine = getPosLine(childRect, lineState.configure)
515508
Object.assign(lineState, {
516-
width: width * scale,
517-
height: height * scale,
518-
top: top * scale + y - siteCanvasRect.y,
519-
left: left * scale + x - siteCanvasRect.x,
509+
width,
510+
height,
511+
top,
512+
left,
520513
position: canvasState.type === 'absolute' || posLine.type,
521514
forbidden: posLine.forbidden
522515
})
523516
} else {
524517
const posLine = getPosLine(rect, configure)
525518
Object.assign(lineState, {
526-
width: width * scale,
527-
height: height * scale,
528-
top: top * scale + y - siteCanvasRect.y,
529-
left: left * scale + x - siteCanvasRect.x,
519+
width,
520+
height,
521+
top,
522+
left,
530523
position: canvasState.type === 'absolute' || posLine.type,
531524
forbidden: posLine.forbidden
532525
})
@@ -537,10 +530,10 @@ const setHoverRect = (element, data) => {
537530

538531
// 设置元素hover状态
539532
Object.assign(hoverState, {
540-
width: width * scale,
541-
height: height * scale,
542-
top: top * scale + y - siteCanvasRect.y,
543-
left: left * scale + x - siteCanvasRect.x,
533+
width,
534+
height,
535+
top,
536+
left,
544537
componentName
545538
})
546539
return undefined

packages/design-core/src/DesignCanvas.vue

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div id="canvas-wrap" ref="canvasRef">
3-
<div ref="siteCanvas" class="site-canvas">
3+
<div ref="siteCanvas" class="site-canvas" :style="siteCanvasStyle">
44
<canvas-container
55
:controller="controller"
66
:materials-panel="materialsPanel"
@@ -14,7 +14,7 @@
1414
</template>
1515

1616
<script>
17-
import { ref, onMounted, watch } from 'vue'
17+
import { ref, onMounted, watch, computed } from 'vue'
1818
import {
1919
CanvasContainer,
2020
CanvasFooter,
@@ -67,6 +67,14 @@ export default {
6767
pageState.properties = null
6868
}
6969
70+
const siteCanvasStyle = computed(() => {
71+
const { scale } = useLayout().getDimension()
72+
return {
73+
height: `calc((100% - var(--base-bottom-panel-height, 30px) - 36px) / ${scale})`,
74+
transform: `scale(${scale})`
75+
}
76+
})
77+
7078
watch(
7179
[() => useCanvas().isSaved(), () => useLayout().layoutState.pageStatus, () => useCanvas().getPageSchema()],
7280
([isSaved, pageStatus, pageSchema], [oldIsSaved, _oldPageStatus, oldPageSchema]) => {
@@ -166,6 +174,7 @@ export default {
166174
request: useHttp(),
167175
ast
168176
},
177+
siteCanvasStyle,
169178
canvasRef
170179
}
171180
}
@@ -182,11 +191,11 @@ export default {
182191
position: relative;
183192
184193
.site-canvas {
185-
height: calc(100% - var(--base-bottom-panel-height, 30px) - 36px);
186194
background: var(--ti-lowcode-breadcrumb-hover-bg);
187195
position: absolute;
188196
overflow: hidden;
189197
margin: 18px 0;
198+
transform-origin: top;
190199
}
191200
}
192201
</style>

0 commit comments

Comments
 (0)