spring弹簧
SpringMotion driven by physics (tension, mass, damping) rather than a set duration.
由张力、质量和阻尼等物理参数驱动的运动,不依赖固定时长。
通过刚度、阻尼、质量和初速度调节真实的弹簧响应。
由张力、质量和阻尼等物理参数驱动的运动,不依赖固定时长。
英文定义逐字保留自 Animation Vocabulary;中文翻译和辨析帮助你选对术语。
springMotion driven by physics (tension, mass, damping) rather than a set duration.
由张力、质量和阻尼等物理参数驱动的运动,不依赖固定时长。
stiffness-tensionHow strongly the spring pulls toward its target. Higher feels snappier.
弹簧拉向目标的力度,数值越高,响应越干脆。
刚度 / 张力决定弹簧拉向目标的力度,是弹簧模型的参数。
dampingHow quickly a spring settles. Lower damping means more bounce and oscillation.
弹簧稳定下来的速度;阻尼越低,回弹和振荡越明显。
阻尼决定弹簧消除振荡的速度;弹簧是包含阻尼在内的完整物理模型。
massHow heavy the animated element feels. More mass makes it slower and more sluggish.
动画元素呈现出的重量;质量越大,运动越慢、越沉。
质量决定元素呈现的重量与惯性;它与刚度、阻尼共同塑造弹簧响应。
bounceA spring that overshoots and settles, adding playfulness.
弹簧越过目标后再稳定下来,为动作增加活泼感。
弹跳是弹簧越过目标后回落的表现,通常由较低阻尼和合适刚度产生。
perceptual-durationHow long a spring feels finished, even though it keeps micro-settling underneath.
弹簧在感知上完成所需的时长,尽管底层仍在进行微小的收敛。
感知时长描述用户觉得弹簧已经结束的时刻;它区别于固定 CSS 时长。
momentumMotion that carries velocity, especially after a drag or interruption.
保留速度并继续前进的运动,常见于拖拽释放或动画中断之后。
动量让动作在拖拽释放或中断后保留速度;弹簧可以接收并延续这份速度。
velocityHow fast and in which direction an element is moving. A spring carries it into the next animation when interrupted, so a flicked element keeps its speed.
元素移动的快慢与方向;弹簧会在中断时把它带入下一段动画,使被快速甩动的元素保留速度。
速度记录运动的快慢与方向;弹簧把它作为下一段响应的初始条件。
interruptible-animationAn animation that can be smoothly redirected mid-flight instead of finishing first.
动画可以在运行途中平滑地改变目标,无需等待当前动作完成。
可打断动画描述运行中可平滑改向的交互能力;弹簧是实现这项能力的一种方式。
目的、频率、触发、时序、可打断性和手势规则共同决定实现。
通过刚度、阻尼、质量和初速度塑造可中断、保留速度的物理响应。
适合中频手势结算和对象跟随;高频微反馈使用高阻尼、短感知时长。
由拖拽释放、目标位置变化或状态切换触发,并传入当前速度。
从当前值向目标收敛;退出动作根据风险控制过冲,避免内容越界。
新目标立即接管当前位移和速度,这是弹簧体验的核心要求。
手势速度以同一坐标系传入弹簧,取消时选择最近安全目标;键盘使用离散目标。
采用高阻尼或即时到达,取消回弹和持续微振荡。
当前参数会同步生成视觉状态 CSS、语义 HTML、所需的原生 JS 运行时和交互提示词。
.motion-demo.motion-demo--spring {
position: relative;
display: grid;
place-items: center;
width: min(100%, 34rem);
min-height: 15rem;
padding: 2rem;
overflow: hidden;
color: #18181b;
background: #fafafa;
border: 1px solid #e4e4e7;
border-radius: 12px;
isolation: isolate;
}
.motion-demo.motion-demo--spring *, .motion-demo.motion-demo--spring *::before, .motion-demo.motion-demo--spring *::after {
box-sizing: border-box;
}
.motion-demo.motion-demo--spring .motion-surface {
position: relative;
display: grid;
gap: 0.65rem;
width: min(100%, 18rem);
padding: 1.25rem;
background: #ffffff;
border: 1px solid #e4e4e7;
border-radius: 8px;
box-shadow: 0 1px 2px rgb(0 0 0 / 6%), 0 10px 28px rgb(0 0 0 / 7%);
}
.motion-demo.motion-demo--spring .motion-line {
display: block;
width: 100%;
height: 0.5rem;
background: #e4e4e7;
border-radius: 999px;
}
.motion-demo.motion-demo--spring .motion-line:last-child { width: 62%; }
.motion-demo.motion-demo--spring .motion-button {
position: relative;
min-height: 2.75rem;
padding: 0.75rem 1.1rem;
color: white;
font: inherit;
font-weight: 700;
background: #18181b;
border: 0;
border-radius: 7px;
cursor: pointer;
}
.motion-demo.motion-demo--spring .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }
.motion-demo.motion-demo--spring .motion-action-row {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-top: 0.85rem;
}
.motion-demo.motion-demo--spring .motion-replay-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--spring .motion-pausable-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--spring button.motion-surface {
color: inherit;
font: inherit;
text-align: start;
cursor: pointer;
}
.motion-demo.motion-demo--spring .motion-replay-button,
.motion-demo.motion-demo--spring .motion-undo-button,
.motion-demo.motion-demo--spring .motion-dismiss-button,
.motion-demo.motion-demo--spring .motion-pause-button {
min-height: 2.75rem;
padding: 0.65rem 0.9rem;
color: #18181b;
font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
background: #ffffff;
border: 1px solid #d4d4d8;
border-radius: 7px;
cursor: pointer;
}
.motion-demo.motion-demo--spring .motion-replay-button:focus-visible,
.motion-demo.motion-demo--spring .motion-undo-button:focus-visible,
.motion-demo.motion-demo--spring .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--spring .motion-pause-button:focus-visible,
.motion-demo.motion-demo--spring [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--spring [data-swipe-target]:focus-visible {
outline: 3px solid rgb(37 99 235 / 32%);
outline-offset: 3px;
}
.motion-demo.motion-demo--spring .motion-status {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.motion-demo.motion-demo--spring .motion-ripple-ink {
position: absolute;
width: 12px;
height: 12px;
pointer-events: none;
background: rgb(255 255 255 / 72%);
border-radius: 50%;
transform: translate(-50%, -50%) scale(0.95);
opacity: 0;
}
.motion-demo.motion-demo--spring .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--spring .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 8px; }
.motion-demo.motion-demo--spring .motion-state--to { background: #18181b; color: white; }
.motion-demo.motion-demo--spring .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--spring .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--spring .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--spring svg { width: min(100%, 20rem); height: auto; }
.motion-demo.motion-demo--spring .motion-surface[data-spring-target] { cursor: pointer; will-change: transform, opacity; }
.motion-demo.motion-demo--spring .motion-surface[data-spring-target]:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }
@keyframes motion-spring-reduced-fade {
from { opacity: 0.84; }
to { opacity: 1; }
}
.force-reduced-motion .motion-demo.motion-demo--spring {
animation: motion-spring-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.force-reduced-motion .motion-demo.motion-demo--spring *,
.force-reduced-motion .motion-demo.motion-demo--spring *::before,
.force-reduced-motion .motion-demo.motion-demo--spring *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.force-reduced-motion .motion-demo.motion-demo--spring .motion-button,
.force-reduced-motion .motion-demo.motion-demo--spring [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--spring [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--spring [data-spring-target] {
transform: none !important;
}
.force-reduced-motion .motion-demo.motion-demo--spring .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--spring .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--spring .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
@media (prefers-reduced-motion: reduce) {
.motion-demo.motion-demo--spring {
animation: motion-spring-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.motion-demo.motion-demo--spring *, .motion-demo.motion-demo--spring *::before, .motion-demo.motion-demo--spring *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.motion-demo.motion-demo--spring .motion-button,
.motion-demo.motion-demo--spring [data-reorder-item],
.motion-demo.motion-demo--spring [data-swipe-target],
.motion-demo.motion-demo--spring [data-spring-target] {
transform: none !important;
}
.motion-demo.motion-demo--spring .motion-path { stroke-dashoffset: 0 !important; }
.motion-demo.motion-demo--spring .motion-word--from { opacity: 0 !important; visibility: hidden; }
.motion-demo.motion-demo--spring .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}采用高阻尼或即时到达,取消回弹和持续微振荡。
| 参数 | 范围 / 选项 | 默认值 | 作用 |
|---|---|---|---|
stiffness | 60–500 | 220 | 调节刚度。 |
damping | 5–60 | 24 | 调节阻尼。 |
mass | 0.5x–3x | 1x | 调节质量。 |
velocity | -20–20 | 0 | 调节初速度。 |
distance | 0px–160px | 48px | 控制元素移动的空间距离。 |