留在原地,向内展开
ANCHORED EXPANSION
点击「筛选」,再试试「更多标签」。
右上角留在原位,面板向左下方生长。
一个节点,两层内容。外框直接改变宽高;面板常驻测量,展开完成后再恢复交互。
离开原位,抵达中央
RECTANGLE MIGRATION
点击任意卡片,留意标题与原位的空隙。
按 Esc
或点击背景,让它回到出发的地方。
布局占位,视觉迁移。原位保留按钮;视觉层移动到视口坐标,返回前重新测量起点。
宽高按数值变化,圆角保持稳定。容器没有整体 scale,文字也就不会被一起拉长。
标题始终可见,辅助内容错峰淡入。开启慢放,观察容器先行、内容跟随的时序。
浮层内可以增加内容。改变窗口大小再关闭,卡片仍会回到重新测量后的位置。
展开实现笔记 · 与博客代码的对应关系
本页内嵌 Motion 12.23.15,使用原生 JavaScript 的 animate(),无需构建或联网。策略 A 对应博客的 motion.div + ResizeObserver;策略 B 将同一个视觉节点临时挂到 body,以 fixed 定位统一使用视口坐标。标题与徽章始终复用原 DOM,单独改变位置;这里没有调用 React 的 layoutId。两种写法保持相同的几何与内容编排原则。
// A:右上角锚定,同一外壳
animate(shell, {
width: panel.offsetWidth,
height: panel.offsetHeight
}, { type: "spring", duration: .4, bounce: 0 });
// ResizeObserver 监听面板的自然尺寸
// 过渡中 inert,完成后解除
// B:占位按钮 + 独立视觉层
const origin = trigger.getBoundingClientRect();
// body / fixed,起终点都是视口坐标
animate(visual, centeredRect(), spring);
// 关闭前重测;动画完成后还原焦点
// closed → opening → open → closing → closed
正常速度:A 几何 400ms,B 几何 480ms,bounce = 0;内容入场延迟 80–120ms,离场无延迟。以动画完成回调推进相位,动画被打断时通过版本号丢弃过期回调。系统或手动开启减少动态效果时,所有时长和延迟归零,焦点与模态语义保持不变。