- 投稿日:2019-08-20T20:24:23+09:00
Svelteのコンポーネントを理解したくて『シュバババッ!』コンポーネントを作ってみた
こんにちは。ちょっと自分でもどこを目指しているのかわからない 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
のコンポーネントを実装していきましょう!コンポーネントのファイルを作成する
components/Syubababa.svelte<script> // JavaScript 書くところ </script> <style> /* CSS 書くところ */ </style> <!-- html 書くところ --> <div/>
.svelte
ファイルの構造はこのようになっています。
Vue.js
と非常によく似ていますが、<template>
タグはなく直接 html タグをコーディングする形になります。コンポーネントの仕様により、実装する順序はまちまちですが、今回は『 シュバババッ! 』を作成した順序を一例として紹介したいと思います。
スタイルを適用させる
components/Syubababa.svelte<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 を使いたい人がいましたら こちら をどうぞ)この状態でも『 シュバッ 』はコンポーネントとして動作します。
index.svelte<script> import Syubababa from '../components/Syubababa.svelte'; </script> <style lang="scss"> </style> <Syubababa/>
index.svelte
の<script>
タグでコンポーネントをimport
し、タグとして<Syubababa/>
をコーディングすると……
と、個性のない(変動的な要素のない)『 シュバッ 』コンポーネントが出来上がりました!続いて、個性を出していきましょう!
コンポーネントにプロパティを持たせる
components/Syubababa.svelte<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 部分を見ていきましょう。components/Syubababa.svelte<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
)側からプロパティを設定してみましょう。index.svelte<script> import Syubababa from '../components/Syubababa.svelte'; </script> <style lang="scss"> </style> <Syubababa duration={"800ms"} delay={"300ms"} height={"50vh"} />
<Syubababa/>
コンポーネントの3つのプロパティを設定すると……
個性が出ましたね!シュバババッ!
ここまでくれば、あとはコンポーネントを並べて『 シュバババッ! 』しましょう!
index.svelte<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
の早さは魅力的で もっと流行ってほしいな― と思います。みなさんも興味を持ったなら、ぜひ使ってみてくださいね
それではお別れは作成途中のポートフォリオサイトのモーダルアニメーションで~
色の勉強をしてみたり、コード書いたり、絵を描いたり、小説を書いたり……。絶賛迷走中。 ↩
- 投稿日:2019-08-20T14:35:37+09:00
cssだけでトグルを実装する
背景
WordPressのサイトを作っていて、ふとトグル(クリックしたら展開するやつ)を実装したいなと思ったんですが、そのためだけにJSを用意しないといけないのがめんどくさいなぁと思ったので、CSSだけで実装する方法を探しました。
次同じようなことする時に忘れていそうなので備忘録的に描いておくことにします。
コード
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> #toggle1{ display: none; } .toggle-inner{ display: none; } #toggle1:checked ~ .toggle-inner{ display: block; } </style> </head> <body> <input type="checkbox" id="toggle1"> <div class="toggle-outer"> <label for="toggle1">クリックして開く▼</label> </div> <div class="toggle-inner"> <hr> <p>長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章長い文章</p> </div> </body> </html>説明
- checkbox(id:toggle1)、toggle-outer、toggle-innerという順番に要素を記述
- toggle-outer:展開・折りたたみをしないエリア
- toggle-inner:展開・折りたたみをするエリア
- toggle-inner配下へ、展開後に表示するコンテンツを用意してdisplay:noneを当てておく
- checkboxがチェックありの場合のみ、toggle-innerがdisplay:blockになるようにする
#toggle1:checked ~ .toggle-inner
で「checkbox(チェック有り)の後ろにあるtoggle-inner」にだけスタイルを適用するという指定ができる(参考:E ~ F-CSS3リファレンス http://www.htmq.com/selector/precede.shtml)スクショ
展開前
展開後
CodePen