diff --git a/vscode/webview-ui/src/codeReader/pageLayout.ts b/vscode/webview-ui/src/codeReader/pageLayout.ts index 66da1e1..972a783 100644 --- a/vscode/webview-ui/src/codeReader/pageLayout.ts +++ b/vscode/webview-ui/src/codeReader/pageLayout.ts @@ -85,6 +85,9 @@ export class PageLayout { private items: ItemBox[] | undefined private cards = new Map() private barHeight: number | undefined + /** 要滚过去、先照常排版着的顶层块(见 settle),和放回去的那一帧 */ + private settling: HTMLElement[] = [] + private release = 0 /** 量 root(块树所在的页面内容)里的卡片,筛选栏是 bar;返回停止观察的函数 */ attach(root: HTMLElement, bar: HTMLElement | null): () => void { @@ -188,9 +191,6 @@ export class PageLayout { return this.itemBoxes() } - private settling: HTMLElement[] = [] - private release = 0 - private settleAround(index: number): void { const items = this.itemBoxes() const view = window.innerHeight diff --git a/vscode/webview-ui/src/codeReader/useReveal.ts b/vscode/webview-ui/src/codeReader/useReveal.ts index 1c07c8b..2e6d107 100644 --- a/vscode/webview-ui/src/codeReader/useReveal.ts +++ b/vscode/webview-ui/src/codeReader/useReveal.ts @@ -6,22 +6,24 @@ import { pageLayout } from './pageLayout' import { revealPlan, scrollTopToShow, uncoveredPlan } from './reveal' import { stickyHeight } from './useStickyScroll' -/** 让一块或属性表里的一行闪几下(codeReader.css 的 [data-flash]);正在闪的同一处再跳一次时从头闪。 */ +/** 正在闪的元素和到点摘掉 data-flash 的计时器 */ +const flashing = new WeakMap() + +/** + * 让一块或属性表里的一行闪几下(codeReader.css 的 [data-flash]);正在闪的同一处再跳一次时从头闪。 + * 闪完(按 CSS 动画的时长)摘掉 data-flash:用计时器而不是等 animationend,滚到画面外被跳过排版的块(content-visibility)里动画停着,等不到它。 + */ export function flash(el: HTMLElement): void { - const running = el.getAnimations().filter(animation => animation instanceof CSSAnimation) - if (running.length > 0) { - for (const animation of running) - animation.currentTime = 0 - return - } - const onEnd = (event: AnimationEvent): void => { - if (event.target !== el) - return - el.removeAttribute('data-flash') - el.removeEventListener('animationend', onEnd) - } - el.addEventListener('animationend', onEnd) + window.clearTimeout(flashing.get(el)) el.setAttribute('data-flash', '') + const animations = el.getAnimations().filter(animation => animation instanceof CSSAnimation) + for (const animation of animations) + animation.currentTime = 0 + const end = Math.max(0, ...animations.map(animation => Number(animation.effect?.getComputedTiming().endTime ?? 0))) + flashing.set(el, window.setTimeout(() => { + el.removeAttribute('data-flash') + flashing.delete(el) + }, end)) } /** 把 el 滚进钉住的筛选栏和卡片下面的视口,量之前先把它那一带排版好(pageLayout.settle)。已经整个看得见就不滚。beforeScroll 在真正滚动前拿到将要落到的位置。 */