The Greatest Showmanという映画を観た後で、そういえばWebサイトのフッターにもエンドロールが必要だなと思い、実装してみた際の記録です。ペロッと実装するだけであれば、CSSのアニメーションですぐにできそうですが、気をつけるべき点がいくつかあったのでまとめました。
Webサイトにエンドロールを実装するときの参考にしてください。
移動距離
お粗末な手書きですが、CSSのアニメーションで移動させる場合の距離の図です。エンドロールのコンテンツ部分をフレームの下に隠れた状況から、上に隠れるまで移動させます。
下に隠す : translateY(100vh)
上に隠す : translateY(-100%)
vh
はviewportに対する高さになるので、translateYを 100vh
とすると下に隠れます。translateの%は、自分のサイズに対する%になるので、100%マイナスに移動させると要素は上に隠れます。
スピード
アニメーションの時間は、CSSで animation-duration
を指定しますが、
.endroll {
animation-duration: 20s;
}
のように固定値で設定してしまうと、要素の高さが変わるとスピード感も変わってしまうので、キャストやスタッフの増減に対応できません。なので、スピードを維持するために、エンドロールを秒速何pxで移動させるかを決めておいて、JavaScriptで動的に設定します。
ストップウォッチを片手に、とある映画のエンドロールのスピードを計測したところ、要素が出てから消えるまでに 10s
を要していたので、フルHDの高さで計算すると
1080px / 10s = 108px/s
になりますが、キリの良いところで 100px/s
にしておきましょう。
さきほど図解したとおり、移動距離は 100vh + 100%
になるので、 animation-duration
は
(100vh + 100%) / 100
で算出できます。
実装
See the Pen endroll by noplan1989 (@noplan1989) on CodePen.
<div class="frame">
<div class="endroll" id="endroll">
<ul>
<li>Michael Gracey</li>
</ul>
<ul>
<li>Hugh Jackman</li>
<li>Zac Efron</li>
<li>・・・</li>
</ul>
</div>
</div>
.frame {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.endroll {
transform: translateY(100vh);
animation-timing-function: linear;
animation-iteration-count: infinite;
&.never-enough {
animation-name: endroll;
}
}
@keyframes endroll {
0% {
transform: translateY(100vh);
}
100% {
transform: translateY(-100%);
}
}
document.addEventListener('DOMContentLoaded', () => {
const endroll = document.getElementById('endroll')
const distance = window.innerHeight + endroll.clientHeight
const duration = distance / 100
endroll.style.animationDuration = `${duration}s`
endroll.classList.add('never-enough')
})
実装はとてもシンプルです。CodePenにあげていますが、一応コードの抜粋も。速度が決まってからアニメーションを開始したいので、アニメーション名を指定するクラスを速度の設定後に追加しています。
animation-play-state
というプロパティでもアニメーションの再生・停止を制御できるようですが、わざわざ paused
にしてから running
にするのも面倒だったので、名前を後からつける形にしました。
Reactの場合
import React, { Component } from "react";
import classNames from "classnames";
class Endroll extends Component {
state = {
duration: 0,
directors: ["Michael Gracey"],
casts: [
"Hugh Jackman",
"Zac Efron",
"・・・"
]
};
componentDidMount() {
const distance = window.innerHeight + this.roll.clientHeight;
const duration = distance / 100;
this.setState({ duration });
}
render() {
return (
<div className="frame">
<div
className={classNames("endroll", {
"never-enough": this.state.duration
})}
ref={el => { this.roll = el; }}
style={{ animationDuration: `${this.state.duration}s` }}
>
<ul>{this.state.directors.map(director => <li>{director}</li>)}</ul>
<ul>{this.state.casts.map(cast => <li>{cast}</li>)}</ul>
</div>
</div>
);
}
}
組み込み先のWebサイトがReactだったので、React版のデモも作りました。CodeSandboxというサービスを初めて使いましたが、シンプルでいいですね。
Reactで作る場合はコンポーネントで閉じていたほうが綺麗なので、CSSのアニメーションには依存しないほうが良さそう。なのだけど、keyframeアニメーション使いたいときはどうすればスッキリするのだろう。JSでアニメーションさせてループさせたらコンポーネントで完結するけど、CSSの方が楽だし迷う。
あとリアルなDOMの高さを取得するという行為に抵抗があるのだけど、他にいい方法はあるのかな。
https://codesandbox.io/s/7jyzkk593j
実際にWebサイトへ埋め込む
Webサイトのフッターにエンドロールを埋め込みました。スクロールしていくと、突然エンドロールが現れます。違和感しかありませんね。
※ 追記
1週間ぐらいフッターにエンドロールをいれた状態にしていたのですが、さすがに邪魔だったので削除しました。
Webサイトにエンドロールは必要か
必要なさそうです。
要素が常に動いているので、ナビゲーションとしての使い勝手は極悪です。かといってホバーで止めたりするのは、エンドロールらしさを阻害するので典型的な悪手です。
エンドロールに必要性や使いやすさを求めるのはあまりにも無粋な話なので、そのような事を考えることはやめにしましょう。
映画の公式サイトに思うところ
多くの映画のサイトで、表示した瞬間に予告編が勝手に再生されるのはどういうつもりなのだろう・・・。予告を観てもらいたいのはわかるけども、観たかったら自分で探して再生するし、邪魔くさいと思っている人の方が多い気がしてならない。実際のところはどうなんだろうか。
映画のサイトに限らず、いきなり音楽や動画を流すサイトは身勝手過ぎると思う。
The Greatest Showman
予告の自動再生はいただけませんが、The Greatest Showmanはとても面白い映画でした。食うに困る少年時代から這い上がり、人を楽しませることに人生を賭け、「The Greatest Show」を実現するべく奔走するお話です。P.T.バーナムという実在したショーマンがベースにされています。とてもベタなストーリーではありますが王道こそ至高であると思いながら震えました。ヒュー・ジャックマンとザック・エフロンがメインのミュージカル映画というのは、キャスティングの時点でずるいと思う。