[Bug] Fix zoom lag of DOM widget (#3714)

This commit is contained in:
Chenlei Hu
2025-05-02 10:58:51 -04:00
committed by GitHub
parent 53372110d3
commit ec8ee49a2c
4 changed files with 48 additions and 23 deletions

View File

@@ -17,7 +17,7 @@
</template>
<script setup lang="ts">
import { useEventListener } from '@vueuse/core'
import { useElementBounding, useEventListener } from '@vueuse/core'
import { CSSProperties, computed, onMounted, ref, watch } from 'vue'
import { useAbsolutePosition } from '@/composables/element/useAbsolutePosition'
@@ -38,18 +38,16 @@ const emit = defineEmits<{
const widgetElement = ref<HTMLElement | undefined>()
/**
* @note Do NOT convert style to a computed value, as it will cause lag when
* updating the style on different animation frames. Vue's computed value is
* evaluated asynchronously.
*/
const style = ref<CSSProperties>({})
const { style: positionStyle, updatePosition } = useAbsolutePosition({
useTransform: true
})
const { style: clippingStyle, updateClipPath } = useDomClipping()
const style = computed<CSSProperties>(() => ({
...positionStyle.value,
...(enableDomClipping.value ? clippingStyle.value : {}),
zIndex: widgetState.zIndex,
pointerEvents:
widgetState.readonly || widget.computedDisabled ? 'none' : 'auto',
opacity: widget.computedDisabled ? 0.5 : 1
}))
const canvasStore = useCanvasStore()
const settingStore = useSettingStore()
@@ -88,13 +86,28 @@ const updateDomClipping = () => {
)
}
/**
* @note mapping between canvas position and client position depends on the
* canvas element's position, so we need to watch the canvas element's position
* and update the position of the widget accordingly.
*/
const { left, top } = useElementBounding(canvasStore.getCanvas().canvas)
watch(
() => widgetState,
(newState) => {
updatePosition(newState)
[() => widgetState, left, top],
([widgetState, _, __]) => {
updatePosition(widgetState)
if (enableDomClipping.value) {
updateDomClipping()
}
style.value = {
...positionStyle.value,
...(enableDomClipping.value ? clippingStyle.value : {}),
zIndex: widgetState.zIndex,
pointerEvents:
widgetState.readonly || widget.computedDisabled ? 'none' : 'auto',
opacity: widget.computedDisabled ? 0.5 : 1
}
},
{ deep: true }
)