修复资源画本转场克隆的遮挡顺序跳变
层级相同的卡片由 DOM 顺序决定遮挡,而转场层原先按来源 key 在前追加克隆,和动画结束后的目标场景顺序不一致,结束瞬间会跳变 改为先按目标场景 DOM 顺序排列,再补只存在于来源里的 key 补充 resourceBookController 用例覆盖来源与目标顺序不同时的克隆顺序
This commit is contained in:
@@ -285,7 +285,12 @@ export function createResourceBookTransitionController() {
|
||||
return;
|
||||
}
|
||||
const target = capture(manager);
|
||||
const keys = new Set([...source.keys(), ...target.keys()]);
|
||||
// 先按目标场景的 DOM 顺序排,再补上只存在于来源里的 key。层级相同的卡片
|
||||
// 由 DOM 顺序决定遮挡关系,顺序不一致会让动画结束的瞬间发生跳变。
|
||||
const keys = [
|
||||
...target.keys(),
|
||||
...Array.from(source.keys()).filter((key) => !target.has(key)),
|
||||
];
|
||||
if (!target.size) {
|
||||
settle();
|
||||
return;
|
||||
|
||||
@@ -178,6 +178,46 @@ describe('resource book FLIP controller', () => {
|
||||
controller.dispose();
|
||||
});
|
||||
|
||||
it('appends clones in the target DOM order so equal z-index cards keep their occlusion', () => {
|
||||
Object.defineProperty(Element.prototype, 'animate', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => ({
|
||||
finished: Promise.resolve({} as Animation),
|
||||
cancel: () => undefined,
|
||||
}),
|
||||
});
|
||||
const root = document.createElement('div');
|
||||
root.innerHTML = `<div class="game-resource-book-scene"><div class="game-resource-book-scene-world">
|
||||
<div class="game-resource-book-scene-card"><div class="game-resource-card" data-resource-card-id="a"></div></div>
|
||||
<div class="game-resource-book-scene-card"><div class="game-resource-card" data-resource-card-id="b"></div></div>
|
||||
</div></div><div class="game-resource-book-transition-layer" inert aria-hidden="true"></div>`;
|
||||
document.body.append(root);
|
||||
vi.spyOn(root, 'getBoundingClientRect').mockReturnValue(rect(0, 0, 800, 600));
|
||||
for (const element of root.querySelectorAll<HTMLElement>(
|
||||
'.game-resource-card',
|
||||
)) {
|
||||
vi.spyOn(element, 'getBoundingClientRect').mockReturnValue(rect());
|
||||
}
|
||||
|
||||
const controller = createResourceBookTransitionController();
|
||||
const token = controller.begin(root);
|
||||
const cardWrapper = root
|
||||
.querySelector<HTMLElement>('[data-resource-card-id="a"]')!
|
||||
.closest<HTMLElement>('.game-resource-book-scene-card')!;
|
||||
cardWrapper.parentElement!.append(cardWrapper);
|
||||
controller.play(root, token, () => undefined);
|
||||
|
||||
const wrappers = Array.from(
|
||||
root.querySelectorAll<HTMLElement>('[data-motion-snapshot]'),
|
||||
);
|
||||
expect(wrappers.map((element) => element.dataset.motionSnapshot)).toEqual([
|
||||
'card:b',
|
||||
'card:a',
|
||||
]);
|
||||
controller.dispose();
|
||||
});
|
||||
|
||||
it('retargets from the current overlay geometry and ignores old completion', async () => {
|
||||
const { root, measure, flights } = setup();
|
||||
const controller = createResourceBookTransitionController();
|
||||
|
||||
Reference in New Issue
Block a user