ハイサイ!オースティンやいびーん!
概要
ChromeとEdgeがサポートしているView Transitions API
をLitと一緒に使うと、とても簡単に再レンダー時のスムーズなアニメーションができます。
アニメーションを付ける部品
ChromiumベースのブラウザでLitの砂場を開きましょう。
この単純なデフォルトの部品にステート変更を加えて、再レンダーを起こすようにします。
import {html, css, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
@customElement('simple-greeting')
export class SimpleGreeting extends LitElement {
static styles = css`p { color: blue }`;
@property()
name = 'World';
firstUpdated() {
setInterval(() => {
const newName = this.name === 'World' ? 'Lit' : 'World';
this.name = newName;
}, 2000);
}
render() {
return html`<p>Hello, ${this.name}!</p>`;
}
}
firstUpdated
はLitが最初にDOMにレンダーした後に呼ばれるメソッドです。その時に2秒おきにname
を変えるようにします。
結果
急に変わるようになっています。これをスムーズに変わるようにしましょう。
View Transitions APIをLitのレンダー時に作動させる
Litのソースコードを調べてみると、LitElement
が実際にDOMの変更を行なってくれる'lit-html
.renderを呼んでくれるのは、
update`というメソッドの中です。
/**
* Updates the element. This method reflects property values to attributes
* and calls `render` to render DOM via lit-html. Setting properties inside
* this method will *not* trigger another update.
* @param changedProperties Map of changed properties with old values
* @category updates
*/
protected override update(changedProperties: PropertyValues) {
// Setting properties in `render` should not trigger an update. Since
// updates are allowed after super.update, it's important to call `render`
// before that.
const value = this.render();
if (!this.hasUpdated) {
this.renderOptions.isConnected = this.isConnected;
}
super.update(changedProperties);
this.__childPart = render(value, this.renderRoot, this.renderOptions);
}
これを自分らの部品で動作を変えたらView Transitions APIを再レンダーのたびに引き起こせそうです。
updateをoverrideする
updateをoverrideして、元の関数を呼ぶようにしましょう。
import {html, css, LitElement, PropertyValues} from 'lit';
import {customElement, property} from 'lit/decorators.js';
@customElement('simple-greeting')
export class SimpleGreeting extends LitElement {
static styles = css`p { color: blue }`;
@property()
name = 'World';
firstUpdated() {
setInterval(() => {
const newName = this.name === 'World' ? 'Lit' : 'World';
this.name = newName;
}, 2000);
}
render() {
return html`<p>Hello, ${this.name}!</p>`;
}
override update(changed: PropertyValues) {
const update = super.update.bind(this, changed);
if (!('startViewTransition' in document)) {
update();
return;
}
// TypeScriptはまだstartViewTransitionを知らないようです
(document as any).startViewTransition(update);
}
}
override update
では、呼びたい関数をupdate
という中間変数にbind
を使ってまとめ、View Transitions APIがサポートされていれば、作動するように呼んでいます。
サポートされていなければ、従来通り呼ぶだけで終わりです。
結果
Gifなのでちょっと荒いかもしれませんが、とても滑らかにアニメートされています!
これでモーダルのアニメーションをほぼ何もせずに、CSSに触れずにできてしまいます!
まとめ
簡単に紹介しましたが、実に様々なアニメーション、それこそネットフリックスのようなアニメーションをとても簡単に実装できるようになったのです。
ブラウザのAPIなので、パフォーマンスもよく、バグも起きないのです。
このView Transition APIについて知りたければ、Chromeの記事をぜひお読みください。
Litじゃなくても使えます!