恢复滚动方案
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
|
||||
/**
|
||||
* 提前约 1.5 屏预热区块内图片解码,避免滚入视口时与 free-scroll rAF 撞车。
|
||||
* onBusyChange(true/false) 供父级短暂降低 canvas 粒子负载。
|
||||
*/
|
||||
export function useImageWarmup(rootRef, { onBusyChange } = {}) {
|
||||
let observer = null
|
||||
let busy = false
|
||||
let warmToken = 0
|
||||
|
||||
const setBusy = (next) => {
|
||||
if (busy === next) return
|
||||
busy = next
|
||||
onBusyChange?.(next)
|
||||
}
|
||||
|
||||
const warmImages = async (el) => {
|
||||
const token = ++warmToken
|
||||
setBusy(true)
|
||||
const imgs = el.querySelectorAll('img[src]')
|
||||
await Promise.allSettled(
|
||||
[...imgs].map((img) => {
|
||||
if (typeof img.decode === 'function') {
|
||||
return img.decode().catch(() => {})
|
||||
}
|
||||
if (img.complete) return Promise.resolve()
|
||||
return new Promise((resolve) => {
|
||||
img.addEventListener('load', resolve, { once: true })
|
||||
img.addEventListener('error', resolve, { once: true })
|
||||
})
|
||||
})
|
||||
)
|
||||
if (token === warmToken) setBusy(false)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const el = rootRef.value
|
||||
if (!el || typeof IntersectionObserver === 'undefined') return
|
||||
const scrollRoot = el.closest('.scrollable-area-body')
|
||||
observer = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry.isIntersecting) warmImages(el)
|
||||
else {
|
||||
warmToken += 1
|
||||
setBusy(false)
|
||||
}
|
||||
},
|
||||
{ root: scrollRoot, rootMargin: '150% 0px', threshold: 0 }
|
||||
)
|
||||
observer.observe(el)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
warmToken += 1
|
||||
observer?.disconnect()
|
||||
observer = null
|
||||
setBusy(false)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user