Skip to content

Commit

Permalink
fix: 修复画布行列容器组件中的分割工具位置错误的问题 (#458)
Browse files Browse the repository at this point in the history
* fix: 修复画布行列容器组件中的分割工具位置错误的问题
  • Loading branch information
gene9831 authored May 17, 2024
1 parent 6d9241e commit 0d36df0
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 79 deletions.
41 changes: 21 additions & 20 deletions packages/canvas/src/components/container/CanvasAction.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ import {
IconEyeclose
} from '@opentiny/vue-icon'
import {
canvasState,
getCurrent,
removeNodeById,
selectNode,
Expand Down Expand Up @@ -379,15 +380,14 @@ export default {
}
}
const getStyleValues = (selectState, siteCanvasWidth, siteCanvasHeight) => {
const getStyleValues = (selectState, canvasSize, labelWidth, optionWidth) => {
const { left, top, width, height, doc } = selectState
const labelRect = labelRef.value.getBoundingClientRect()
const optionRect = optionRef.value.getBoundingClientRect()
const { width: canvasWidth, height: canvasHeight } = canvasSize
// 标签宽度和工具操作条宽度之和加上间距
const fullRectWidth = labelRect.width + optionRect.width + OPTION_SPACE
const fullRectWidth = labelWidth + optionWidth + OPTION_SPACE
// 是否 将label 标签放置到底部,判断 top 距离
const isLabelAtBottom = top <= LABEL_HEIGHT
const isLabelAtBottom = top < LABEL_HEIGHT
const labelAlign = new Align({
alignLeft: true,
horizontalValue: 0,
Expand All @@ -396,7 +396,7 @@ export default {
})
// 是否将操作栏放置到底部,判断当前选中组件底部与页面底部的距离。
const isOptionAtBottom = siteCanvasHeight - top - height > OPTION_BAR_HEIGHT
const isOptionAtBottom = canvasHeight - top - height >= OPTION_BAR_HEIGHT
const optionAlign = new Align({
alignLeft: false,
horizontalValue: 0,
Expand All @@ -410,39 +410,39 @@ export default {
// 选中框宽度小于标签宽度和工具操作条宽度之和加上间距
// 如果labe宽度大于选中框宽度,并且label右侧已经超出画布,则label对齐右侧
const isLabelAlignRight = labelRect.width > width && left + labelRect.width + scrollBarWidth > siteCanvasWidth
const isLabelAlignRight = labelWidth > width && left + labelWidth + scrollBarWidth > canvasWidth
if (isLabelAlignRight) {
labelAlign.align(positions.RIGHT)
}
// 如果option宽度大于选中框宽度,并且option左侧已经超出画布,则option对齐左侧
const isOptionAlignLeft = optionRect.width > width && left + width - optionRect.width < 0
const isOptionAlignLeft = optionWidth > width && left + width - optionWidth < 0
if (isOptionAlignLeft) {
optionAlign.align(positions.LEFT)
}
if (isLabelAtBottom === isOptionAtBottom) {
// 标签框和工具操作框都在顶部或者都在底部
if (left + fullRectWidth < siteCanvasWidth) {
if (left + fullRectWidth < canvasWidth) {
// 都放在左侧
labelAlign.align(positions.LEFT)
optionAlign.align(positions.LEFT, labelRect.width + OPTION_SPACE)
optionAlign.align(positions.LEFT, labelWidth + OPTION_SPACE)
} else {
// 都放在右侧
optionAlign.align(positions.RIGHT)
labelAlign.align(positions.RIGHT, optionRect.width + OPTION_SPACE)
labelAlign.align(positions.RIGHT, optionWidth + OPTION_SPACE)
}
}
} else {
if (left < 0) {
labelAlign.align(positions.LEFT, Math.min(-left, width - fullRectWidth))
}
if (left + width + scrollBarWidth > siteCanvasWidth) {
if (left + width + scrollBarWidth > canvasWidth) {
optionAlign.align(
positions.RIGHT,
Math.min(left + width + scrollBarWidth - siteCanvasWidth, width - fullRectWidth)
Math.min(left + width + scrollBarWidth - canvasWidth, width - fullRectWidth)
)
}
}
Expand All @@ -454,8 +454,7 @@ export default {
}
watchPostEffect(async () => {
let { left } = props.selectState
const { top, width, height, doc } = props.selectState
const { left, top, width, height, doc } = props.selectState
// nextTick后ref才能获取到元素。需要把监听的依赖放在await之前,否则无法监听变化
await nextTick()
Expand All @@ -470,15 +469,17 @@ export default {
return
}
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
const scale = useLayout().getScale()
const canvasRect = canvasState.iframe.getBoundingClientRect()
const { width: labelWidth } = labelRef.value.getBoundingClientRect()
const { width: optionWidth } = optionRef.value.getBoundingClientRect()
left -= ((1 - scale) / 2) * siteCanvasRect.width
// canvas容器中,iframe以及iframe之外的元素clientRect的尺寸都是缩放过的,除以scale得到原始大小
const { labelStyleValue, optionStyleValue } = getStyleValues(
{ left, top, width, height, doc },
siteCanvasRect.width * scale,
siteCanvasRect.height
{ width: canvasRect.width / scale, height: canvasRect.height / scale },
labelWidth / scale,
optionWidth / scale
)
labelStyle.value = labelStyleValue
Expand Down
3 changes: 1 addition & 2 deletions packages/canvas/src/components/container/CanvasContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ import {
updateRect,
getElement,
dragStart,
getOffset,
selectNode,
initCanvas,
clearLineState,
Expand Down Expand Up @@ -101,7 +100,7 @@ export default {
// 如果是点击右键则打开右键菜单
if (event.button === 2) {
openMenu(getOffset(event.target), event)
openMenu(event)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/canvas/src/components/container/CanvasDivider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export default {
<style lang="less" scoped>
.divider-wrapper {
position: fixed;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
Expand Down Expand Up @@ -239,7 +239,7 @@ export default {
}
.divider-line {
position: fixed;
position: absolute;
border: 1px dashed var(--ti-lowcode-common-primary-color);
z-index: 2;
}
Expand Down
34 changes: 21 additions & 13 deletions packages/canvas/src/components/container/CanvasMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<span>{{ item.name }}</span>
<span v-if="item.items"><icon-right></icon-right></span>
</div>
<ul v-if="item.items && current === item" class="sub-menu menu-item">
<ul v-if="item.items && current === item" class="sub-menu menu-item" :style="subMenuStyles">
<template v-for="(subItem, subIndex) in item.items" :key="subIndex">
<li
:class="[{ 'menu-item-disabled': subItem.check && !subItem.check?.() }]"
Expand All @@ -33,7 +33,7 @@

<script lang="jsx">
import { ref, reactive, nextTick } from 'vue'
import { getConfigure, getController, getCurrent, copyNode, removeNodeById } from './container'
import { canvasState, getConfigure, getController, getCurrent, copyNode, removeNodeById } from './container'
import { useLayout, useModal, useCanvas } from '@opentiny/tiny-engine-controller'
import { iconRight } from '@opentiny/vue-icon'
Expand All @@ -45,27 +45,35 @@ const menuState = reactive({
const current = ref(null)
const menuDom = ref(null)
const subMenuStyles = ref(null)
export const closeMenu = () => {
menuState.show = false
current.value = null
}
export const openMenu = (offset, event) => {
const { x, y } = offset
const { getScale } = useLayout()
export const openMenu = (event) => {
menuState.position = {
// 位置处于画布右侧边缘时需要调整显示方向 TODO
left: event.clientX * getScale() + x + 2 + 'px',
top: event.clientY * getScale() + y + 'px'
left: event.clientX + 2 + 'px',
top: event.clientY + 'px'
}
menuState.show = sessionStorage.getItem('pageInfo') ? true : false
nextTick(() => {
if (menuDom.value) {
const { bottom, height, top } = menuDom.value.getBoundingClientRect()
if (bottom > document.body?.clientHeight) {
menuState.position.top = top - height + 'px'
const { right, bottom, width, height } = menuDom.value.getBoundingClientRect()
const canvasRect = canvasState.iframe.getBoundingClientRect()
if (bottom > canvasRect.bottom) {
menuState.position.top = `${parseInt(menuState.position.top) - height}px`
}
if (right > canvasRect.right) {
menuState.position.left = `${parseInt(menuState.position.left) - width - 2}px`
}
// sub-menu样式width为100px,少于100宽度的空白区域则放置到左侧
if (right + 100 < canvasRect.right) {
subMenuStyles.value = { right: '-100px' }
} else {
subMenuStyles.value = { left: '-100px' }
}
}
})
Expand Down Expand Up @@ -226,6 +234,7 @@ export default {
close,
current,
menuDom,
subMenuStyles,
actionDisabled,
onShowChildrenMenu
}
Expand All @@ -235,7 +244,7 @@ export default {

<style lang="less" scoped>
.context-menu {
position: fixed;
position: absolute;
z-index: 10;
}
.menu-item {
Expand Down Expand Up @@ -276,7 +285,6 @@ export default {
&.sub-menu {
width: 100px;
position: absolute;
right: -100px;
top: -2px;
}
}
Expand Down
7 changes: 3 additions & 4 deletions packages/canvas/src/components/container/CanvasResize.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ import { canvasState } from './container'
export default {
setup() {
const sizeStyle = computed(() => {
const { width, maxWidth, minWidth, scale } = useLayout().getDimension()
const { width, height, maxWidth, minWidth } = useLayout().getDimension()
return {
width,
height,
maxWidth,
minWidth,
height: `${100 / scale}%`,
transform: `scale(${scale}) translateY(-${(100 / scale - 100) / 2}%)`
minWidth
}
})
Expand Down
25 changes: 13 additions & 12 deletions packages/canvas/src/components/container/CanvasResizeBorder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<script>
import { reactive, watch } from 'vue'
import { useLayout } from '@opentiny/tiny-engine-controller'
import { getCurrent, updateRect, selectState, querySelectById } from './container'
export default {
Expand Down Expand Up @@ -38,12 +39,17 @@ export default {
}
const handleResize = (event, type) => {
if (!props.iframe) {
return
}
let { clientX, clientY } = event
const iframeRect = props.iframe.getBoundingClientRect()
const scale = useLayout().getScale()
if (type === 'iframe' && props.iframe) {
const iframeRect = props.iframe.getBoundingClientRect()
clientX += iframeRect.left
clientY += iframeRect.top
if (type !== 'iframe') {
clientX = (clientX - iframeRect.left) / scale
clientY = (clientY - iframeRect.top) / scale
}
const { parent, schema } = getCurrent()
Expand All @@ -65,14 +71,9 @@ export default {
const parentWidth = parseInt(window.getComputedStyle(parentDomNode).width, 10)
// 最大宽度不能大于父组件宽度
if (newWidth >= parentWidth) {
newWidth = parentWidth
}
newWidth = Math.min(newWidth, parentWidth)
// 最小宽度32
if (newWidth <= 32) {
newWidth = 32
}
newWidth = Math.max(newWidth, 32)
schema.props.flexBasis = `${newWidth}px`
schema.props.widthType = 'fixed'
Expand Down Expand Up @@ -186,7 +187,7 @@ export default {

<style lang="less" scoped>
.resize-border {
position: fixed;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
Expand Down
39 changes: 16 additions & 23 deletions packages/canvas/src/components/container/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,16 +348,13 @@ const setSelectRect = (element) => {
element = element || getDocument().body

const { left, height, top, width } = getRect(element)
const { x, y } = getOffset(element)
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
const componentName = getCurrent().schema?.componentName || ''
const scale = useLayout().getScale()
clearHover()
Object.assign(selectState, {
width: width * scale,
height: height * scale,
top: top * scale + y - siteCanvasRect.y,
left: left * scale + x - siteCanvasRect.x,
width,
height,
top,
left,
componentName,
doc: getDocument()
})
Expand Down Expand Up @@ -481,9 +478,6 @@ const setHoverRect = (element, data) => {
const configure = getConfigure(componentName)
const rect = getRect(element)
const { left, height, top, width } = rect
const { x, y } = getOffset(element)
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
const scale = useLayout().getScale()

hoverState.configure = configure

Expand Down Expand Up @@ -512,23 +506,22 @@ const setHoverRect = (element, data) => {
if (childEle) {
const childRect = getRect(childEle)
const { left, height, top, width } = childRect
const { x, y } = getOffset(childEle)
const posLine = getPosLine(childRect, lineState.configure)
Object.assign(lineState, {
width: width * scale,
height: height * scale,
top: top * scale + y - siteCanvasRect.y,
left: left * scale + x - siteCanvasRect.x,
width,
height,
top,
left,
position: canvasState.type === 'absolute' || posLine.type,
forbidden: posLine.forbidden
})
} else {
const posLine = getPosLine(rect, configure)
Object.assign(lineState, {
width: width * scale,
height: height * scale,
top: top * scale + y - siteCanvasRect.y,
left: left * scale + x - siteCanvasRect.x,
width,
height,
top,
left,
position: canvasState.type === 'absolute' || posLine.type,
forbidden: posLine.forbidden
})
Expand All @@ -539,10 +532,10 @@ const setHoverRect = (element, data) => {

// 设置元素hover状态
Object.assign(hoverState, {
width: width * scale,
height: height * scale,
top: top * scale + y - siteCanvasRect.y,
left: left * scale + x - siteCanvasRect.x,
width,
height,
top,
left,
componentName
})
return undefined
Expand Down
Loading

0 comments on commit 0d36df0

Please sign in to comment.