Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修复画布行列容器组件中的分割工具位置错误的问题 #458

Merged
merged 7 commits into from
May 17, 2024
Merged
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 @@ -100,7 +99,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) {
gene9831 marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -346,16 +346,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 @@ -479,9 +476,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 @@ -510,23 +504,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 @@ -537,10 +530,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
Loading