💨
Svelteで流れる文字(marquee)を実装する方法
おはようございます。DE-TEIUです。
今回は皆大好きmarqueeタグをSvelteで実装してみました。
ソースコードはGitHubに公開しています。
成果物
実装
Marqueeコンポーネント
流れる文字の実装は、1つのコンポーネント内で完結させています。
Svelteでは、1つのコンポーネント内にJavaScript、CSS、HTMLのコードが存在するので、分けて解説します。
JavaScript
JavaScriptでは、流れる文字のHTML要素のスタイルを、画面サイズに合わせて初期化しています。
Marquee.svelte(JS部分)
import { onMount } from "svelte"; // 画面初期化時イベント
export let text; // 表示する文字列(親コンポーネントから渡される)
let style = "";
const resize = () => {
// 画面幅と文字列全体の幅から、文字が流れる速度を決める
// この値を小さくすればより速く流れるようになります
const duration = Math.trunc(window.innerWidth / 60) + text.length / 10;
// 1文字の幅を16pxとして、文字列全体の幅をざっくり算出
// フォントサイズが変わるならここを適宜調整する
const textWidth = text.length * 16;
// 流れる文字要素の幅とアニメーションの秒数を要素のスタイルに指定
style = `animation-duration:${duration}s;` + `width:${textWidth}px;`;
};
onMount(() => {
resize(); // 画面リサイズ時のスタイル更新処理を呼び出す
});
CSS
CSSでは、
- 表示するテキストの初期位置を画面の右端からはみ出させる
- CSSアニメーションで流れる文字
の2点を実装しています
Marquee.svelte(CSS部分)
.marquee {
width: 100%; /** 幅は親要素に合わせる */
overflow: hidden; /** 親要素からはみ出した部分は非表示とする */
}
.marquee_text {
padding-left: 100%; /** 表示する要素が完全に画面右端からはみ出すように位置を調整 */
text-align: left;
white-space: nowrap;
animation-name: marquee; /** 流れる文字のアニメーション設定 */
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes marquee {
from {
transform: translate(0%);
}
100%,
to {
transform: translate(-100%); /* 画面左端まで移動する */
}
}
HTML+α
HTMLの実装はこうなります。
実際に流れる文字を表示する要素の他に、画面のリサイズにも対応するため、windowオブジェクトにリサイズイベントを設定しておきます。
Marquee.svelte(HTML部分)
<svelte:window on:resize={resize} />
<div class="marquee">
<div class="marquee_text" {style}>{text}</div>
</div>
呼び出し方
呼び出し方は単純です。
作成したMarquee.Svelteを、呼び出したいsvelteコンポーネントのscript内でimportします。
App.svelte(JS部分)
import Marquee from "./Marquee.svelte";
あとはHTML内の任意の場所でMarqueeコンポーネントを呼び出します。
App.svelte(HTML部分)
<main>
<Marquee text="こんな感じで文字が流れます。" />
</main>
参考資料
Svelteは公式のドキュメントがわかりやすくて助かりますね。
Lifecycle / onMount • Svelte Tutorial
Props / Declaring props • Svelte Tutorial
余談
後で知ったんですが、npmにsvelte-marqueeというライブラリが存在してました。
自前で実装するのが面倒な場合はこちらを使用しても良いかもしれません。
Discussion