算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
fluid-interfaces【设计与创意】Design and review principles for fluid, gestural, physically-responsive interfaces, distilled from Apple's WWDC 2018 "Designing Fluid Interfaces" talk (the iPhone X gestural UI team). Use when designing or reviewing touch/gesture interactions, spring-based motion, drag-to-dismiss or swipe gestures, scroll physics, elastic/ rubberband behaviors, redir…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Source: Apple WWDC 2018 session 803, "Designing Fluid Interfaces" (Chan Karunamuni,
Nathan de Vries, Marcos Alonso — Human Interface team, built the iPhone X gestural UI).
Full transcript in references/transcript.md.
Core thesis: an interface feels fluid when it feels like an extension of the user's mind and body, not a computer being operated. This isn't about frame rate — a 60fps interface can still feel "off." It comes from matching the interface's behavior to how our bodies and minds actually move: continuously, redirectably, and in response to real physical momentum.
Use this skill to audit existing gesture/motion code (find file:line violations of the principles below) or to design new interactions from scratch.
Respond instantly. Any perceptible delay between touch and reaction breaks
the illusion of directness. Audit every tap, press, and drag start for latency —
not just swipes. Delays creep in via debounce timers, setTimeout, animation
queues, or waiting for a gesture to fully end before giving feedback.
Allow constant redirection and interruption. Users should be able to change their mind mid-gesture without waiting for the current animation/gesture to finish. Detect direction changes via acceleration spikes, not velocity thresholds + timers — a sudden deceleration/reversal in finger motion is detectable faster than "wait until velocity drops below X for Y ms." If a new gesture can't interrupt an in-flight one, that's a violation.
Maintain spatial consistency. Objects should enter and exit the screen via symmetric, consistent paths (mimics real-world object permanence). If something enters from the right, it should exit to the right — not to the bottom. Broken symmetry (e.g. push-in from right, pop-out downward) reads as "sending it away" rather than "going back," and is disorienting.
Hint in the direction of the gesture. Intermediate/pressed states should visually grow toward the final state along the same trajectory (e.g. Control Center modules bulge toward the finger before popping open). This lets users predict the outcome before completing the gesture.
Keep touch lightweight, but amplify the output. A short, light touch input (a flick) should produce a magnified result (a long scroll). Don't require large, laborious physical motion for large on-screen effects — build an "inertial profile" from position/velocity/force and extend it into an amplified, momentum-preserving motion after the finger lifts.
Rubberband at boundaries and handoffs. Never hard-stop at an edge — softly resist and settle back (rubber-banding) so the interface is legibly "still responding" rather than frozen or broken. This also applies to handoffs between two tracked behaviors (e.g. dock → app sheet): they should hand off in a smooth curve, not a sudden ownership swap.
Design smooth frames of motion, not just high frame rate. Fast motion at a fixed frame rate can strobe if there's too much visual change between adjacent frames. Mitigations: raise frame rate, add motion blur, or use motion stretching (elastic squash/stretch in the direction of travel — used on the iPhone X app-launch icon animation). The takeaway: it's not just fps, it's what changes between frames.
Design behavior, not prescribed animation. Real-world motion isn't an animation curve decided in advance — it's a continuous negotiation between the object's physics and the forces acting on it (your touch, gravity, friction). Prefer continuously-running dynamic behaviors (springs) over one-shot timed animations wherever a gesture drives the motion.
Timed/duration-based animations hand control to the designer for a fixed window, then hand it back — a call-and-response pattern that breaks down the moment a user wants to interrupt or redirect mid-animation. Spring-based (elastic) behaviors are always running and can be redirected/retargeted at any instant, which is what makes constant interruption (principle 2) actually implementable.
damping (0–100%): how much overshoot. 100% = no overshoot (critically
damped), 0% = oscillates forever.response: how quickly the value approaches its target. (Technical terms:
damping ratio + frequency response — look these up for exact conversions,
e.g. iOS UISpringTimingParameters / SwiftUI .spring(response:dampingFraction:).)When a gesture ends (e.g. flinging a floating element toward one of several target zones — "endpoints"), don't just snap to the nearest endpoint by position. That ignores velocity and makes the interaction feel like it's fighting the user — you'd need to drag almost all the way to the target for it to register.
Instead, project the position forward using the release velocity and a
deceleration rate (reuse UIScrollView-style deceleration so it matches the
muscle memory users already have from scrolling), then pick the endpoint nearest
to that projected (imaginary, never-rendered) position:
func project(initialVelocity: CGFloat, decelerationRate: CGFloat) -> CGFloat {
// UIScrollView.DecelerationRate.normal ≈ 0.998
return (initialVelocity / 1000) * decelerationRate / (1 - decelerationRate)
}
// projectedPosition = currentPosition + project(velocity, decelerationRate)
// -> pick nearest endpoint to projectedPosition, not to currentPosition
This generalizes beyond position — it works for scale and rotation projections too. Any "settle to nearest state on release" interaction (snap points, corner docking, paged carousels with variable velocity) should project momentum, not just check current position.
UISwipeGestureRecognizer); prefer ones that stream
position/velocity/pressure/size throughout (raw touches, pan/pressure
recognizers).Gestural affordances aren't self-evident, so teach them cheaply:
axiom-haptics for pairing this with haptic cues.Report findings as file:line + which of the 8 principles or checklist items is
violated + the concrete user-facing symptom (e.g. "drag handler re-centers the
element under the finger on line 42 — breaks relative-offset tracking, so the
dragged element jumps on grab"). Don't flag stylistic animation-curve choices
that aren't tied to one of the principles above — this skill is about
interaction physics, not general animation taste (use 12-principles-of-animation
or make-interfaces-feel-better for that).