こんにちは。ちょっと自分でもどこを目指しているのかわからない 1 あずきしろもち(@azukisiromochi) です。
今回は Svelte
のコンポーネントの話。
前フリ
※ループさせていないので、右下の [Rerun] ボタンを押して試してみてください
See the Pen Syubababa!!! by あずきしろもち (@azukisiromochi) on CodePen.
CSSアニメーションを勉強しようと思ってこういうやつ作ったんです。『 シュバババッ! 』って感じのやつ。
(あとで気づいたけど、右スクロールするとオブジェクト見えてるなw)
いま、ポートフォリオサイトを作成していて、モーダルをオープンするときのアニメーションに、この『 シュバババッ! 』を使ってみたいなーと思ったわけです。
どんなコンポーネントにするのか
そもそもコンポーネントって?
Svelte
の公式リファレンスにはコンポーネントの定義が記載されていません(たぶん)。
Svelte
は Vue.js
に非常に近い構文ということもあって、そちらの定義を確認してみましょう。
小さく、自己完結的で、(多くの場合)再利用可能なインスタンスをコンポーネントという
キーワードは
- 小さい
- 自己完結的
- 再利用可能
みたいですね。
『シュバババッ!』はどんなコンポーネントになるのか?
先程の CodePen
のコードでは
<div class="syubababa a"></div>
<div class="syubababa b"></div>
<div class="syubababa c"></div>
<div class="syubababa d"></div>
<div class="syubababa e"></div>
こんな感じに <div>
要素が並んでいました。
つまり、5つの『 シュバッ 』が順々にアニメーションしているんです。
コンポーネントのキーワードにあった 再利用可能 に、非常によく当てはまると思いませんか?
ということで、この1つの『 シュバッ 』を Svelte
のコンポーネントとして定義して進めてみましょう!
コンポーネントの仕様を明確にしよう!
コンポーネントは、1つの『 シュバッ 』の単位にすることは決めました。
ですが、ただこの『 シュバッ 』を並べるだけでは面白くありません。
『 シュバッ 』の 高さ を変えたり、 速度 を変えたり、 動き出すタイミング を変えたり……
このあたり(仕様)を明確にしていきます。
<div class="syubababa a"></div>
<div class="syubababa b"></div>
<div class="syubababa c"></div>
<div class="syubababa d"></div>
<div class="syubababa e"></div>
もう一度、このコードに戻ります。
それぞれの <div>
に共通の .syubababa
クラスと、個々の .a
.b
.c
.d
.e
クラスがあります。
コンポーネント化に置き換えると、 .syubababa
クラスがコンポーネントの共通仕様で、 .a
.b
.c
.d
.e
クラスが動的に変動させることのできる要素になるでしょう。
例えば .a
の場合、
.a {
animation-duration: 800ms;
animation-delay: 700ms;
}
と設定されていますし、 .d
の場合、
.d {
animation-delay: 1400ms;
height: 10vh;
}
と設定されています。
コンポーネントの変動的な要素としては、次のようになりそうです。
animation-duration | 仕様 |
---|---|
animation-duration | アニメーション一回分の時間の長さ ≒ 速度 |
animation-delay | アニメーションの開始タイミング |
height | 『 シュバッ 』の高さ |
コンポーネントの単位では、
// Set style `animation-duration` (default: 800ms)
let duration = '';
// Set style `animation-delay` (default: 0)
let delay = '';
// Set style `height` (default: 15vh)
let height = '';
この3種類のプロパティーを扱って『 シュバッ 』を変動させていこうと思います。
コンポーネントを実装していく
ここまでで『 シュバババッ! 』は、『 シュバッ 』コンポーネントをいくつか並べて実現することを決めました。
また、『 シュバッ 』コンポーネントは、 duration
delay
height
をプロパティに持ち、それぞれの『 シュバッ 』に個性を持たせることも決めました。
それでは順を追って Svelte
のコンポーネントを実装していきましょう!
コンポーネントのファイルを作成する
<script>
// JavaScript 書くところ
</script>
<style>
/* CSS 書くところ */
</style>
<!-- html 書くところ -->
<div/>
.svelte
ファイルの構造はこのようになっています。
Vue.js
と非常によく似ていますが、 <template>
タグはなく直接 html タグをコーディングする形になります。
コンポーネントの仕様により、実装する順序はまちまちですが、今回は『 シュバババッ! 』を作成した順序を一例として紹介したいと思います。
スタイルを適用させる
<script>
// JavaScript 書くところ
</script>
<style lang="scss">
$color1: #e1315b;
$color2: #f47d4a;
$color3: #ffff42;
$color4: #00cffa;
div {
background: $color1;
height: 15vh;
width: 10vw;
margin-left: -15vw;
animation-name: fadeIn;
animation-duration: 800ms;
animation-timing-function: ease;
// animation-iteration-count: 1;
animation-fill-mode:forwards;
}
@keyframes fadeIn {
15% { background: $color1; }
30% { background: $color2; }
45% { background: $color3; }
50% {
transform: scaleX(15) skew(-30deg);
transform-origin: 0% 50%;
}
75% { border-radius: 30% 20% / 40% 15%; }
80% { background: $color4; }
90% { box-shadow: -20px 10px 10px 10px rgba(0, 0, 0, .8); }
100% {
transform: translatex(120vw) scaleX(2) skew(0deg);
transform-origin: 0% 50%;
margin-left: 0;
}
}
</style>
<!-- html 書くところ -->
<div/>
CodePen
の実装を参考に CSS を設定しました。
SCSS を使ってしまっていますが、色を調整するための変数としてしか利用していません。
( Svelte
や Sapper
で SCSS を使いたい人がいましたら こちら をどうぞ)
この状態でも『 シュバッ 』はコンポーネントとして動作します。
<script>
import Syubababa from '../components/Syubababa.svelte';
</script>
<style lang="scss">
</style>
<Syubababa/>
index.svelte
の <script>
タグでコンポーネントを import
し、タグとして <Syubababa/>
をコーディングすると……
と、個性のない(変動的な要素のない)『 シュバッ 』コンポーネントが出来上がりました!
続いて、個性を出していきましょう!
コンポーネントにプロパティを持たせる
<script>
// Set style `animation-duration` (default: 800ms)
export let duration = '';
// Set style `animation-delay` (default: 0)
export let delay = '';
// Set style `height` (default: 15vh)
export let height = '';
</script>
<script>
タグだけ切り出しましたが、仕様のところで決めた3つの変動要素(変数)を export
させています。
これで親コンポーネントから『 シュバッ 』コンポーネントにプロパティを設定し、個性を出すことができるようになります。
変数を export
させたのはいいですが、実際の html に変動要素のスタイルを適用する必要があります。
今度は html 部分を見ていきましょう。
<div style="animation-duration: {duration}; animation-delay: {delay}; height: {height}"/>
<div>
タグの style
要素に animation-duration
animation-delay
height
を設定し、それぞれに対して、 <script>
タグで宣言した変数を設定しています。
Vue.js
の場合は {{ hoge }}
でバインドしますが、 Svelte
の場合は { hoge }
でバインドします。
それでは、親コンポーネント( index.svelte
)側からプロパティを設定してみましょう。
<script>
import Syubababa from '../components/Syubababa.svelte';
</script>
<style lang="scss">
</style>
<Syubababa duration={"800ms"} delay={"300ms"} height={"50vh"} />
<Syubababa/>
コンポーネントの3つのプロパティを設定すると……
個性が出ましたね!
シュバババッ!
ここまでくれば、あとはコンポーネントを並べて『 シュバババッ! 』しましょう!
<script>
import Syubababa from '../components/Syubababa.svelte';
</script>
<style lang="scss">
</style>
<Syubababa duration={"800ms"} delay={"700ms"} />
<Syubababa duration={"700ms"} delay={"1000ms"} height={"30vh"} />
<Syubababa duration={"600ms"} delay={"1200ms"} height={"20vh"} />
<Syubababa delay={"1400ms"} height={"10vh"} />
<Syubababa delay={"1500ms"} height={"25vh"} />
まとめ
Svelte
のコンポーネントは Vue.js
のものと非常に似ていて、 Vue.js
を触ったことのある人ならすんなり使えるのではないでしょうか。
今回は紹介していませんが、 Svelte
にも <slot>
が用意されており、より自由度の高いコンポーネントが作れると思います。
両方とも使っている身としては、 Svelte
の早さは魅力的で もっと流行ってほしいな― と思います。
みなさんも興味を持ったなら、ぜひ使ってみてくださいね
それではお別れは作成途中のポートフォリオサイトのモーダルアニメーションで~
-
色の勉強をしてみたり、コード書いたり、絵を描いたり、小説を書いたり……。絶賛迷走中。 ↩