From c3bedb95dde4ee2343423380c48f436e9c065fdc Mon Sep 17 00:00:00 2001 From: SepVeneto Date: Thu, 2 Jan 2025 18:18:52 +0800 Subject: [PATCH] fix(free-dom): improve auto-sizing and mask handling --- packages/core/__tests__/freedom.spec.ts | 8 ++-- packages/core/src/components/freeDomWrap.ts | 42 +++++++------------ packages/core/src/hooks/use-mask.ts | 4 +- packages/core/src/style/free-dom.scss | 5 +-- .../examples/free-dom/auto-expand/index.vue | 8 ++-- .../free-dom/transform-scale/combine.vue | 6 ++- 6 files changed, 31 insertions(+), 42 deletions(-) diff --git a/packages/core/__tests__/freedom.spec.ts b/packages/core/__tests__/freedom.spec.ts index 174450c..dd90d7c 100644 --- a/packages/core/__tests__/freedom.spec.ts +++ b/packages/core/__tests__/freedom.spec.ts @@ -128,7 +128,7 @@ describe('auto correct', () => { test('when scene mounted', async () => { const INIT = { x: -20, y: 100, w: 20, h: 20 } const pos = ref(INIT) - const wrap = mount(h( + mount(h( FreeScene, { style: 'width: 100px; height: 100px;', @@ -139,9 +139,7 @@ describe('auto correct', () => { }, () => h('span', 'test')), )) await nextTick() - hackCss(wrap) - await nextTick() - await nextTick() + expect(pos.value.x).toBe(0) expect(pos.value.y).toBe(80) }) @@ -164,7 +162,7 @@ describe('auto correct', () => { data: () => ({ nodeList: [] }), }) await nextTick() - hackCss(wrapper) + // hackCss(wrapper) await wrapper.setData({ nodeList, }) diff --git a/packages/core/src/components/freeDomWrap.ts b/packages/core/src/components/freeDomWrap.ts index 96c6d37..e8fdff3 100644 --- a/packages/core/src/components/freeDomWrap.ts +++ b/packages/core/src/components/freeDomWrap.ts @@ -2,23 +2,20 @@ import type { ExtractPropTypes, PropType } from 'vue-demi' import { computed, defineComponent, + onMounted, provide, reactive, ref, shallowRef, toRefs, watch, - watchEffect, } from 'vue-demi' import { SceneToken, createRender } from '../util' import markLine from './markLine' import { useDefaultSlot, useEventBus, useMask, useOperateHistory } from '../hooks' import { freeDomProps } from './freeDom' import type { INode, IPos } from '../types' -import { useElementBounding } from '@vueuse/core' -import debugInit from 'debug' -const debug = debugInit('freeDom:wrap') export const freeDomWrapProps = { diff: { @@ -73,36 +70,25 @@ export const FreeDomWrap = defineComponent({ const eventBus = useEventBus() const nodes = ref([]) const history = useOperateHistory(nodes) - const width = ref(props.width) - const height = ref(props.height) + const width = ref() + const height = ref() const rectRef = shallowRef() - const wrapRect = useElementBounding(rectRef) const wrapStyle = computed(() => ({ height: height.value + 'px', width: width.value + 'px', })) - watchEffect(() => { - width.value = props.width - height.value = props.height + onMounted(() => { + if (rectRef.value) { + const { width: w, height: h } = window.getComputedStyle(rectRef.value) + width.value = props.width || Math.round(parseFloat(w)) || 0 + height.value = props.height || Math.round(parseFloat(h)) || 0 + } }) - watch([ - wrapRect.width, - wrapRect.height, - () => nodes.value.length, - ], ([w, h]) => { - debug('update size') - - if (!w || !h) return - - width.value = w - height.value = h - emit('update:width', w) - emit('update:height', h) - + watch([width, height, () => nodes.value.length], () => { runCorrect() - }, { immediate: true }) + }) const selectedNodes = computed(() => nodes.value.filter(node => node.node.selected)) @@ -269,14 +255,16 @@ export const FreeDomWrap = defineComponent({ const main = createRender( 'section', { - ref: 'rectRef', class: 'vv-free-dom--scene', style: this.wrapStyle, }, )(slotList) const wrap = (comp: any) => createRender( 'section', - {}, + { + ref: 'rectRef', + style: 'overflow: hidden;', + }, {}, { onMousedown: this.mask.handleMousedown, diff --git a/packages/core/src/hooks/use-mask.ts b/packages/core/src/hooks/use-mask.ts index 0562f79..9b9fa4c 100644 --- a/packages/core/src/hooks/use-mask.ts +++ b/packages/core/src/hooks/use-mask.ts @@ -90,8 +90,8 @@ export function useMask( // evt.offsetX, evt.offsetY计算的是基于target计算的 // 因此当容器内存在子元素或缩放方向会经过mask时offset不能代表在容器内的相对位置 function offsetFormat(evt: MouseEvent) { - const offsetX = evt.clientX - rect.x.value - const offsetY = evt.clientY - rect.y.value + const offsetX = (evt.clientX - rect.x.value) / props.transformScale + const offsetY = (evt.clientY - rect.y.value) / props.transformScale return { x: offsetX, y: offsetY, diff --git a/packages/core/src/style/free-dom.scss b/packages/core/src/style/free-dom.scss index 908ee72..caa505d 100644 --- a/packages/core/src/style/free-dom.scss +++ b/packages/core/src/style/free-dom.scss @@ -12,8 +12,7 @@ .vv-free-dom--draggable__disabled { cursor: initial; } -.vv-free-dom--draggable__mask.vv-free-dom--draggable__selected::after, -.vv-free-dom--draggable__mask.vv-free-dom--draggable__selected:focus-visible { +.vv-free-dom--draggable__mask.vv-free-dom--draggable__selected::after { content: ''; z-index: 1; display: block; @@ -23,7 +22,7 @@ top: 0; left: 0; background: var(--vv-free-dom--selected); - outline: 2px dashed var(--vv-free-dom--theme); + border: 2px dashed var(--vv-free-dom--theme); &::selection { background-color: transparent !important; } diff --git a/packages/examples/free-dom/auto-expand/index.vue b/packages/examples/free-dom/auto-expand/index.vue index d014ca2..187eca1 100644 --- a/packages/examples/free-dom/auto-expand/index.vue +++ b/packages/examples/free-dom/auto-expand/index.vue @@ -1,9 +1,11 @@