Skip to content

Commit

Permalink
perf: improve draggable el perf
Browse files Browse the repository at this point in the history
  • Loading branch information
festoney8 committed Oct 13, 2024
1 parent 6cd56c7 commit 582cd27
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 48 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 4.0.3

- 修复:播放页 视频信息相关功能
- 优化:拖拽面板性能

## 4.0.2

Expand Down
84 changes: 53 additions & 31 deletions src/components/PanelComp.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
<template>
<div
ref="panel"
:style="[
{
width: widthPercent + 'vw',
height: heightPercent + 'vh',
minWidth: minWidth + 'px',
minHeight: minHeight + 'px',
},
style,
]"
:style="[panelStyle, { transform: panelTransform }]"
class="no-scrollbar fixed z-[10000000] select-none overflow-auto overscroll-none rounded-xl bg-white shadow-lg"
>
<div ref="bar" class="sticky top-0 z-10 w-full cursor-move bg-[#00AEEC] py-1.5 text-center">
Expand Down Expand Up @@ -37,8 +29,10 @@
</template>

<script setup lang="ts">
import { useDraggable, useElementBounding } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import { Position, useDraggable, useElementBounding, useWindowSize } from '@vueuse/core'
import { computed, ref } from 'vue'
const emit = defineEmits(['close'])
const props = defineProps<{
title: string
Expand All @@ -48,34 +42,62 @@ const props = defineProps<{
minHeight: number // 单位px
}>()
const emit = defineEmits(['close'])
const panel = ref<HTMLElement | null>(null)
const bar = ref<HTMLElement | null>(null)
const windowSize = useWindowSize({ includeScrollbar: false })
const initPos = {
x: windowSize.width.value / 2 - Math.max((windowSize.width.value * props.widthPercent) / 100, props.minWidth) / 2,
y:
windowSize.height.value / 2 -
Math.max((windowSize.height.value * props.heightPercent) / 100, props.minHeight) / 2,
}
const { width, height } = useElementBounding(bar, { windowScroll: false }) // bar元素长宽
const { x, y, style } = useDraggable(panel, {
initialValue: {
x: innerWidth / 2 - Math.max((innerWidth * props.widthPercent) / 100, props.minWidth) / 2,
y: innerHeight / 2 - Math.max((innerHeight * props.heightPercent) / 100, props.minHeight) / 2,
},
// 限制拖拽范围
let rAF: number
const maxPos = computed(() => {
return {
x: windowSize.width.value - width.value,
y: windowSize.height.value - height.value,
}
})
const { x, y } = useDraggable(panel, {
initialValue: initPos,
handle: computed(() => bar.value),
preventDefault: true,
onMove: (pos: Position) => {
cancelAnimationFrame(rAF)
rAF = requestAnimationFrame(() => {
if (pos.x < 0) {
pos.x = 0
}
if (pos.y < 0) {
pos.y = 0
}
if (pos.x > maxPos.value.x) {
pos.x = maxPos.value.x
}
if (pos.y > maxPos.value.y) {
pos.y = maxPos.value.y
}
})
},
})
// 限制拖拽范围
watch([x, y], ([newX, newY]) => {
if (newX < 0) {
x.value = 0
}
if (newY < 0) {
y.value = 0
}
if (newY + height.value > innerHeight) {
y.value = innerHeight - height.value
}
if (newX + width.value > innerWidth) {
x.value = innerWidth - width.value
const panelStyle = computed(() => {
return {
width: props.widthPercent + 'vw',
height: props.heightPercent + 'vh',
minWidth: props.minWidth + 'px',
minHeight: props.minHeight + 'px',
left: initPos.x + 'px',
top: initPos.y + 'px',
}
})
const panelTransform = computed(() => {
return `translate(${x.value - initPos.x}px, ${y.value - initPos.y}px)`
})
</script>
47 changes: 30 additions & 17 deletions src/views/SideBtnView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
</div>
</template>
<script setup lang="ts">
import { Position, useDraggable, useElementBounding, useStorage } from '@vueuse/core'
import { Position, useDraggable, useElementBounding, useStorage, useWindowSize } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import {
useCommentFilterPanelStore,
Expand Down Expand Up @@ -93,38 +93,51 @@ const btnPos = useStorage('bili-cleaner-side-btn-pos', { right: 10, bottom: 180
const isDragging = ref(false)
const windowSize = useWindowSize({ includeScrollbar: false })
const maxPos = computed(() => {
return {
x: windowSize.width.value - width.value,
y: windowSize.height.value - height.value,
}
})
useDraggable(target, {
initialValue: {
x: document.documentElement.clientWidth - btnPos.value.right,
y: document.documentElement.clientHeight - btnPos.value.bottom,
},
preventDefault: true,
handle: computed(() => target.value),
onMove: (position: Position) => {
onMove: (pos: Position) => {
isDragging.value = true
btnPos.value.right = document.documentElement.clientWidth - position.x - width.value
btnPos.value.bottom = document.documentElement.clientHeight - position.y - height.value
btnPos.value.right = maxPos.value.x - pos.x
btnPos.value.bottom = maxPos.value.y - pos.y
},
onEnd: () => {
setTimeout(() => {
isDragging.value = false
}, 100)
}, 50)
},
})
// 限制拖拽范围
let rAF: number
watch(btnPos.value, (newBtnPosition) => {
if (newBtnPosition.right < 0) {
btnPos.value.right = 0
}
if (newBtnPosition.bottom < 0) {
btnPos.value.bottom = 0
}
if (newBtnPosition.bottom + height.value > document.documentElement.clientHeight) {
btnPos.value.bottom = document.documentElement.clientHeight - height.value
}
if (newBtnPosition.right + width.value > document.documentElement.clientWidth) {
btnPos.value.right = document.documentElement.clientWidth - width.value
}
cancelAnimationFrame(rAF)
rAF = requestAnimationFrame(() => {
if (newBtnPosition.right < 0) {
btnPos.value.right = 0
}
if (newBtnPosition.bottom < 0) {
btnPos.value.bottom = 0
}
if (newBtnPosition.bottom + height.value > document.documentElement.clientHeight) {
btnPos.value.bottom = document.documentElement.clientHeight - height.value
}
if (newBtnPosition.right + width.value > document.documentElement.clientWidth) {
btnPos.value.right = document.documentElement.clientWidth - width.value
}
})
})
</script>

0 comments on commit 582cd27

Please sign in to comment.