AnimationDirectiveDOMAdded in v15.7

Decode

A readout locking on: every character shows random glyphs that change quickly, then settles on the real one, left to right. The line never moves while it plays.

Installation

Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.

import { Component } from '@angular/core';
import { WrDecode } from 'ngwr/animations/decode';

@Component({ imports: [WrDecode] })
export class MyComponent {}

Basic

Put wrDecode on the element that holds the text. By default it plays once, when most of the element is in view. A glyph keeps the shape of the character it stands in for, so the word shape stays readable, and spaces never scramble.

<wr-tag color="primary" outlined><span wrDecode>Developer experience</span></wr-tag>
<h2 wrDecode>Release 15.7 is out.</h2>
Developer experience

Release 15.7 is out.

Hover

trigger="hover" plays on every pointer enter and on focus, of the element or of its closest focusable ancestor, so a label inside a button decodes when the button is reached by keyboard too. A play in progress is never restarted.

<button wr-btn outlined type="button"><span wrDecode trigger="hover">Hover or focus me</span></button>

Glyphs

glyphs is the set every slot draws from, instead of the shape of its own character: binary for a readout, a few symbols for a glitch.

<p wrDecode glyphs="01">Resolved in 2.4 ms</p>

Resolved in 2.4 ms

Timing

delay is the pause between the trigger and the first glyph; the text stands as authored meanwhile. stagger is the gap between one slot locking and the next, 36 ms unset, and the locks spread over 1.2 s at most. The colour a glyph paints in before it locks is --wr-decode-tint, mixed from the text's own colour.

<p wrDecode delay="400" stagger="80">Slow enough to watch each slot lock.</p>
.readout {
  --wr-decode-tint: color-mix(in srgb, var(--wr-color-primary) 50%, transparent);
}

Slow enough to watch each slot lock.

Accessibility

PartBehaviour
Screen readers While the slots play they are aria-hidden, and a visually hidden copy of the text stands beside them, so the text is announced once and the noise never. At rest the element holds its original text nodes.
Reduced motion Under prefers-reduced-motion: reduce nothing plays, in either trigger mode: the text is shown as authored. The demos on this page follow the same setting.
Keyboard In hover mode focus plays it too, read on the closest focusable ancestor, so a label inside a button or a link behaves the same for a pointer and for Tab.
Layout The real character stays in its slot, hidden, and the glyph is painted over it out of flow, so the line keeps its width and nothing around it moves.
Server The server renders the plain text. The slots are created in the browser, after the first render, and in view mode only where IntersectionObserver exists.

API

NameDescriptionTypeDefault
triggerview plays once, the first time most of the host is in the viewport. hover plays on every pointer enter and focus of the host or its closest focusable ancestor, but never restarts while already playing.WrDecodeTrigger'view'
glyphsThe characters random glyphs are drawn from, for every slot. Unset, each slot draws from the shape of its own character: uppercase letters and digits for an uppercase letter, lowercase for lowercase, digits for a digit, a few symbols for anything else.string | nullnull
staggerGap between one slot locking and the next, in ms. Unset, 36. Either way the locks spread over 1.2 s at most, so for a long text the gap shrinks until the last slot locks by then.number | nullnull
delayPause between the trigger and the first glyph, in ms. The text stands as authored meanwhile.number0

CSS variables

Set these on the element itself, with a rule more specific than its Declared on selector. In a global stylesheet, put a class of yours on an ancestor it really has: <body> for an overlay panel, which renders outside your markup. In a component stylesheet the selector alone works, but only for an element in that component's own template. A value on a wrapper or :root is shadowed, because ngwr/animations/decode declares each default on its own element.

VariableDefaultDeclared on
--wr-decode-easevar(--wr-ease-out).wr-decode
--wr-decode-settle240ms.wr-decode and inline on the element, written by the component from its inputs or its state — a rule holds only until the component writes
--wr-decode-tintcolor-mix(in srgb, currentColor 45%, transparent).wr-decode

See also