防抖优化
This commit is contained in:
@@ -51,26 +51,33 @@ export function initAdaptive(designWidth = DEFAULT_DESIGN_WIDTH) {
|
|||||||
|
|
||||||
const useZoom = isZoomSupported()
|
const useZoom = isZoomSupported()
|
||||||
|
|
||||||
// 首次:渲染前同步应用一次,避免首帧闪烁
|
// rAF 帧对齐节流:把同一帧内多次 resize 合并为一次
|
||||||
apply()
|
let rafId = null
|
||||||
window.addEventListener('resize', onResize)
|
// 真实写入节流 + 尾随兜底:拖拽/设备模拟期间 resize 高频触发,
|
||||||
// 从后台标签切回来时,若期间窗口尺寸变化(因 hidden 被跳过)需补算一次
|
// 若每帧都写 html.zoom 会强制整页重排+重绘导致卡顿,因此限制真实写入频率
|
||||||
document.addEventListener('visibilitychange', onVisibilityChange)
|
let lastAppliedScale = -1
|
||||||
|
let lastWriteAt = 0
|
||||||
|
let trailingTimer = null
|
||||||
|
const WRITE_MIN_INTERVAL = 100 // ms
|
||||||
|
|
||||||
/**
|
function computeScale() {
|
||||||
* 真正的缩放计算与写入。
|
const root = document.documentElement
|
||||||
* 比例基于 window.innerWidth(窗宽),它不受页面自身 zoom 缩放影响,
|
const width = window.innerWidth || (root && root.clientWidth) || designWidth
|
||||||
* 可避免因滚动条宽度变化造成的“缩放-比例”联动回摆。
|
const ratio = width / designWidth
|
||||||
*/
|
// 收敛到 [MIN_SCALE, MAX_SCALE],规避极端宽高的异常比例
|
||||||
function apply() {
|
return Math.min(MAX_SCALE, Math.max(MIN_SCALE, ratio))
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeScale(scale) {
|
||||||
const root = document.documentElement
|
const root = document.documentElement
|
||||||
if (!root) {
|
if (!root) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const width = window.innerWidth || root.clientWidth || designWidth
|
// 值未变化:跳过,避免冗余的样式失效/整页重排
|
||||||
const ratio = width / designWidth
|
if (Math.abs(scale - lastAppliedScale) < 1e-4) {
|
||||||
// 收敛到 [MIN_SCALE, MAX_SCALE],规避极端宽高的异常比例
|
return
|
||||||
const scale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, ratio))
|
}
|
||||||
|
lastAppliedScale = scale
|
||||||
|
|
||||||
if (scale === 1) {
|
if (scale === 1) {
|
||||||
clearScale(root)
|
clearScale(root)
|
||||||
@@ -105,8 +112,11 @@ export function initAdaptive(designWidth = DEFAULT_DESIGN_WIDTH) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rAF 帧对齐节流:把同一帧内多次 resize 合并为一次应用,实时且顺滑
|
/** 立即计算并写入一次(带值变化守卫) */
|
||||||
let rafId = null
|
function applyNow() {
|
||||||
|
lastWriteAt = Date.now()
|
||||||
|
writeScale(computeScale())
|
||||||
|
}
|
||||||
|
|
||||||
function onResize() {
|
function onResize() {
|
||||||
if (document.hidden) {
|
if (document.hidden) {
|
||||||
@@ -117,15 +127,35 @@ export function initAdaptive(designWidth = DEFAULT_DESIGN_WIDTH) {
|
|||||||
}
|
}
|
||||||
rafId = window.requestAnimationFrame(() => {
|
rafId = window.requestAnimationFrame(() => {
|
||||||
rafId = null
|
rafId = null
|
||||||
if (!document.hidden) {
|
if (document.hidden) {
|
||||||
apply()
|
return
|
||||||
}
|
}
|
||||||
|
const now = Date.now()
|
||||||
|
if (trailingTimer) {
|
||||||
|
clearTimeout(trailingTimer)
|
||||||
|
}
|
||||||
|
// 距上次真实写入已超过阈值才立即写入,其余情况靠尾随兜底,避免满帧整页重排
|
||||||
|
if (now - lastWriteAt >= WRITE_MIN_INTERVAL) {
|
||||||
|
applyNow()
|
||||||
|
}
|
||||||
|
// 尾随:拖拽/改变尺寸停下后,确保落到最终窗口尺寸
|
||||||
|
trailingTimer = setTimeout(applyNow, WRITE_MIN_INTERVAL)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function onVisibilityChange() {
|
function onVisibilityChange() {
|
||||||
if (!document.hidden) {
|
if (!document.hidden) {
|
||||||
apply()
|
// 从后台切回时补算一次
|
||||||
|
if (trailingTimer) {
|
||||||
|
clearTimeout(trailingTimer)
|
||||||
|
}
|
||||||
|
applyNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 首次:渲染前同步应用一次,避免首帧闪烁
|
||||||
|
applyNow()
|
||||||
|
window.addEventListener('resize', onResize)
|
||||||
|
// 从后台标签切回来时,若期间窗口尺寸变化(因 hidden 被跳过)需补算一次
|
||||||
|
document.addEventListener('visibilitychange', onVisibilityChange)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user