Heavy views
A view with thousands of nodes, or with frosted glass, is costly to scale and blur on every frame. flatten keeps a photo of the view you are in, with SnapDOM, and moves the photo while the view sits behind. Zoom into a bright tile with it on, then off.
Turn it on
Install SnapDOM and its plugins next to Zumly, and hand over snapdom and stream:
npm install zumly @zumer/snapdom @zumer/snapdom-plugins
import Zumly from 'zumly'
import { snapdom } from '@zumer/snapdom'
import { stream } from '@zumer/snapdom-plugins/stream'
new Zumly({ mount: '.canvas', initialView: 'home', views, flatten: { snapdom, stream } })
Both are optional peer dependencies: npm install zumly alone does not bring them. Without a bundler, import them from a CDN, as the example does. If SnapDOM is missing, Zumly says so once in the console and the views stay as they are.
What happens
- While you are in a view, its photo follows it: the stream repaints only what changed, at most ten times a second.
- You zoom into something: the view you leave shows the photo, as it was at that moment. Its content is still there and laid out, only hidden, so the blur and dimming, clicks on siblings and every driver work as before.
- You come back: the real view returns, crossfading from the photo.
- A photo is never taken during a transition. If there is none yet, the zoom moves the real view. Nothing waits for a photo.
When it pays off
Three zooms in and three out, with a clock, spinners and numbers changing in every view. Chrome on a MacBook; a dropped frame is one the screen never got.
| Views | Without | animateEffects: false | With flatten |
|---|---|---|---|
| Cards, about 3,000 nodes | 6.8% dropped | 5.2% | 1.3%, no hitch |
| Frosted glass | 52% dropped, 48% at rest | 48%, 48% at rest | 0%, 0% at rest |
| Orbit dials (light) | 0.6% | 0% | left alone |
With the processor four times slower, frosted glass drops 47% without and 0.6% with flatten.
A light view gains nothing, so flatten leaves it alone. It photographs a view with at least minNodes elements, or with backdrop-filter inside. Mark a view data-flatten="true" to photograph it anyway, or data-flatten="false" to keep it live behind (a video, a game). Views with an iframe stay live: SnapDOM can only draw a placeholder for it.
Options
| Option | Default | Description |
|---|---|---|
snapdom | the global snapdom | The snapdom function from @zumer/snapdom. |
stream | none | The stream function from @zumer/snapdom-plugins/stream. It keeps the photo current; without it, only views that hold still are flattened. |
minNodes | 800 | Views with fewer elements are photographed only if they use backdrop-filter. |
scale | 1 | Resolution of the photo. The blur behind hides its softness; without effects, 2 keeps text behind sharp, for four times the memory. |
Good to know
- A zoom never starts from old content. When keeping a photo current would cost more than half the main thread, that view simply moves as itself. What makes it costly: a value that changes often inside a box with no solid background, or over other content (a badge on top of cards). Give such a value a solid background and it costs a few milliseconds.
- Animations are not followed: a spinner shows the angle it had when its area was last repainted, and a CSS transition shows its end only after the next repaint there. Behind a blur, nobody notices.
- Without
streamthere is one photo, taken again once the view stops changing. A view that changed since its photo moves as itself, so views with live data are not flattened. - A view behind stands still while it is there. When you come back, the real view crossfades in, with whatever changed meanwhile.
- A zoom-in starts a frame or two later: hiding the content of the view that grows takes a moment, about 25 ms on a laptop and 65 ms on a phone-class processor. The motion that follows is the smooth part.
- Each view behind keeps its photo in a canvas: width × height × 4 bytes, times the pixel ratio squared.
Try the cheap fix first
transitions: { animateEffects: false } applies the blur at once instead of animating it. It needs nothing else, and with many nodes it already takes out part of the stutter. Reach for flatten when that is not enough: frosted glass, thousands of nodes, or a slow device.