Skip to content

PlAnimateZoom

Content arriving from the middle of where it will end up. Use it for the one thing on a screen that is meant to interrupt, a confirmation, a result, a number that has just landed.

React
tsx
import { PlAnimateZoom } from 'plass-ui';

<PlAnimateZoom>
  <PlBox color="success">92</PlBox>
</PlAnimateZoom>;
dart
import 'package:plass_ui/plass_ui.dart';

const PlAnimateZoom(
  child: PlBox(color: PlassColor.success, child: Text('92')),
);

Props

PropTypeDefaultDescription
mode'in' | 'out''in'Whether the content comes forward or falls away. out is the same keyframe run backwards
fromnumber0.4The scale it starts from, as a multiple of its final size. Above 1 it arrives oversized and settles back, which reads as coming towards the reader
fadebooleantrueFades in as it zooms
durationsharednumber320How long one run takes, in milliseconds. A number, never a CSS string
delaysharednumber0How long before it starts, in milliseconds
easingsharedstringthe house curveThe easing curve, written the way CSS writes it
repeatsharednumber | 'infinite'1How many times it runs. 'infinite' rather than Infinity, because that word is what reaches CSS
alternatesharedbooleanfalseRuns every other pass backwards, so a repeat returns instead of jumping
pausedsharedbooleanfalseHolds the animation where it is
triggershared'mount' | 'visible' | 'hover' | 'manual''mount'What starts it: mount as soon as it is on the page, visible when it is scrolled into view, hover while the pointer or focus is on it, manual only when play says so
playsharedbooleanRuns it when trigger is manual. Each false → true starts it over
oncesharedbooleantrueWith trigger="visible", whether it runs only the first time. Off, it runs again every time the element comes back into view
thresholdsharednumber0.2With trigger="visible", how much of the element has to be on screen before it counts as visible, from 0 to 1
timelineshared'auto' | 'view''auto'What advances the animation: the clock, or the reader's scroll position. view ignores duration, delay, repeat and trigger, and runs against range instead
rangesharedstring'entry 0% cover 45%'As CSS writes an animation-range. Only read when timeline is view
staggersharednumber0Milliseconds added to each child's delay. 0 plays the box itself; anything else moves the effect onto the children and takes it off the box
durationStepsharednumber0Milliseconds added to each child's duration. Negative is allowed; floored at 0
reversesharedbooleanfalseRuns the set from the last child to the first. Only the order turns round; each child still plays forwards
renderReactElement | (props, state) => ReactElementRenders something other than a <div>
PropTypeDefaultDescription
modePlassAnimateModePlassAnimateMode.enterWhether the content comes forward or falls away. enter/exit rather than in/out, because in is a reserved word in Dart
fromdouble0.4The scale it starts from, as a multiple of its final size. Above 1 it arrives oversized and settles back, which reads as coming towards the reader
fadebooltrueFades in as it zooms
durationsharedDurationDuration(milliseconds: 320)How long one run takes, in milliseconds. A number, never a CSS string
delaysharedDurationDuration.zeroHow long before it starts, in milliseconds
curvesharedCurve?the house curveThe easing curve, written the way CSS writes it
repeatsharedint?1How many times it runs. null is what never stops: there is no 'infinite' to write, and -1 would be a sentinel a caller has to look up
alternatesharedboolfalseRuns every other pass backwards, so a repeat returns instead of jumping
pausedsharedboolfalseHolds the animation where it is
triggersharedPlassAnimateTriggerPlassAnimateTrigger.mountWhat starts it: mount as soon as it is on the page, visible when it is scrolled into view, hover while the pointer or focus is on it, manual only when play says so
playsharedboolfalseRuns it when trigger is manual. Each false → true starts it over
oncesharedbooltrueWith trigger="visible", whether it runs only the first time. Off, it runs again every time the element comes back into view
thresholdshareddouble0.2With trigger="visible", how much of the element has to be on screen before it counts as visible, from 0 to 1
child * WidgetWhat arrives

Every native <div> attribute passes straight through, and render swaps the element for another one.

duration and delay are Durations, curve is a Curve, and repeat is an int? where null never stops.

There is deliberately no origin. A zoom anchored to a corner is a grow, and the library does not offer two spellings of one idea — use PlAnimateGrow when the effect should come out of something next to it.

The ten shared settings — duration, delay, easing, repeat, alternate, paused, trigger, play, once, threshold — are the same on every PlAnimate* component. The four trigger values are shown on the PlAnimateFade page. timeline="view" and range are there too, and hand the effect to the reader's scroll position instead of the clock.

Three more move the effect off the box and onto the things inside it: stagger holds each child back by its position, durationStep gives each one a longer or shorter run than the last, and reverse starts from the end of the set. They are on all six single-keyframe effects and are shown on the PlAnimateFade page.

Examples

from

More than twice a grow's distance by default, and that is the whole difference in feel. Below 1 the content comes forward out of the page; above it, it arrives oversized and settles back, which reads as coming towards the reader.

React

Announcing a result

What the effect is for. One thing on the screen, once, at the moment it becomes true.

React

Accessibility

  • Under prefers-reduced-motion the animation is dropped entirely and the content is simply there.
  • The wrapper adds no role and no label. A result that has to be announced needs a live region of its own — the effect is what a reader sees, not what a screen reader is told.
  • The travel is long enough to resample text noticeably. Keep it for a figure, a glyph or a small card; a paragraph wants PlAnimateFade.
  • Nothing repeats by default, and this is the effect to leave that way. Something that zooms twice is something that failed to arrive the first time.
  • When the platform has animations turned off (MediaQuery.disableAnimations) the effect is dropped entirely and the content is simply there.
  • The widget adds no semantics of its own. A result that has to be announced needs a Semantics(liveRegion: true) of its own — the effect is what a reader sees, not what a screen reader is told.
  • The travel is long enough to resample text noticeably. Keep it for a figure, a glyph or a small card; a paragraph wants PlAnimateFade.
  • Nothing repeats by default, and this is the effect to leave that way.

Differences from the React build

ReactFlutterWhy
mode="in" | "out"PlassAnimateMode.enter / .exitin is a reserved word in Dart.
fade draws an always-present opacity layerno Opacity widget at all when fade is offOne fewer layer to composite.
renderFlutter has no polymorphic element.
duration, delay in millisecondsDurationThe framework already has the type.
easing as a CSS stringcurve, a CurveDart's own name for the same thing.
repeat: number | 'infinite'int?, null never stopsThere is no 'infinite' to write, and -1 would be a sentinel a caller has to look up.
trigger="visible" via IntersectionObserverwatches the nearest ScrollableThere is no observer here; with no scrollable above it there is nothing to watch, so it runs.
prefers-reduced-motionMediaQuery.disableAnimationsThe platform's own signal.
stagger, durationStep, reverseThe React build writes the effect onto the children themselves, so the caller's own layout is untouched. Flutter has no stylesheet to lay a set out with, so a staggered effect would have to own the row or the column as well — which is what PlAnimateAppear is, and six more of it would be six more of it.
timeline="view"animation-timeline is a CSS property with no counterpart here. A scroll-linked effect in Flutter is an AnimationController driven from a ScrollPosition, which is an application's own wiring rather than something a widget takes as a prop.
className, styleThere is no class list and no style attribute to pass through.

Released under the MIT License