Vue3のトランジションとアニメーション
こんにちは、あっくんです。先日、たつの市に行ってきました。姫路からたつのまで車の運転の練習をさせていただきました。1週間に1回は車に乗るようにしています。運転するのが本当に怖いですが、乗るたびに怖さが減ってる感じがします。教えてくれる人に感謝です。ちなみに車庫入れは全然できていません。ここから頑張ります。今回はVue3のトランジションとアニメーションについてやっていきましょう。
トランジションで状態操作
Vue3では「状態を変化させる操作」が多いです。
トランジションは、スタイルシートの状態変化を扱うための機能を提供します。↓のように記述します。
<transition name="名前">
…….表示内容………
</transition>
Code language: HTML, XML (xml)
表示をON/OFFにする
トランジション利用のサンプルを作っていきましょう。
Viteでslot.appプロジェクトを作成しましょう。
開発するディレクトリでターミナルに↓を打ち込みましょう
npm init vite-app transition_app
cd transition_app
npm install
HelloWorld.vueを編集します。
<template>
<div class="alert alert-primary">
<h2>{{ title }}</h2>
<p>{{ message }}</p>
<button class="btn btn-primary m-3" v-on:click="doAction">
{{ btn }}
</button>
<transition name="transit">
<p v-if="flg" class="alert alert-light h5">Transition context!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
title: "Trans&Anim",
message: "This is Transition sample!",
flg: true,
btn: "Show/Hide",
};
},
methods: {
doAction() {
this.flg = !this.flg;
},
},
};
</script>
Code language: HTML, XML (xml)
App.vueを編集します
<template>
<HelloWorld />
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HelloWorld,
},
};
</script>
Code language: HTML, XML (xml)
index.htmlを編集します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Transition App</title>
<!-- CSS only -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
crossorigin="anonymous"
/>
<!-- JavaScript Bundle with Popper -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
crossorigin="anonymous"
></script>
</head>
<body>
<h1 class="bg-secondary text-white h4 p-3">Vue3 Transition</h1>
<div class="container">
<div id="app"></div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
↑npm run devをターミナルで打ち込んでボタンをクリックすると下のメッセージがON/OFFになります。
v-ifを使って、flgの値をチェックしています。これがtrueなら表示され、falseなら表示されません。
フェードイン/フェードアウト
トランジションはあらかじめ決められたルールにしたがってスタイルシートのクラスを定義します。これは、トランジションの名前の後に予約された名前入を追加する形で指定します。
Enter関係
Enter関係は消えていたものが画面に現れる時のトランジションです。
名前-enter-active
Enterトランジションがアクティブになったとき
名前-enter-from
Enterトランジションが開始されるとき
名前-enter
Enterトランジションがスタートしたとき
名前-enter-to
Enterトランジションが完了したとき
Leave関係
Leave関係は画面にあるものが消える時のトランジションです。
名前-leave-active
Leaveトランジションがアクティブになったとき
名前-leave-from
Leaveトランジションが開始されるとき
名前-leave
Leaveトランジションがスタートしたとき
名前-leave-to
Leaveトランジションが完了したとき
フェードイン/フェードアウト
<template>
<div class="alert alert-primary">
<h2>{{ title }}</h2>
<p>{{ message }}</p>
<button class="btn btn-primary m-3" v-on:click="doAction">
{{ btn }}
</button>
<transition name="transit">
<p v-if="flg" class="alert alert-light h5">Transition context!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
title: "Trans&Anim",
message: "This is Transition sample!",
flg: true,
btn: "Show/Hide",
};
},
methods: {
doAction() {
this.flg = !this.flg;
},
},
};
</script>
<style>
.trans {
background-color: black;
color: white;
padding: 10px;
font-size: 20pt;
}
.transit-enter-active {
transition: opacity 0.5s;
}
.transit-leave-active {
transition: opacity 5s;
}
.transit-enter {
opacity: 0;
}
t .transit-enter-from {
opacity: 0;
}
.transit-enter-to {
opacity: 1;
}
.transit-leave {
opacity: 1;
}
.transit-leave-to {
opacity: 0;
}
</style>
Code language: HTML, XML (xml)
↑npm run devをターミナルで打ち込むんで、ボタンをクリックすると、ゆっくりメッセージが消えていきます。もう一度クリックすると、ボタンが表れます。
クラスをチェック
アクティブ時の設定
.transit-enter-active {
transition: opacity 0.5s;
}
.transit-leave-active {
transition: opacity 5s;
Code language: CSS (css)
transitionは操作するスタイル名と経過時間を指定します。Enterのときにopacityを0.5秒で変化させます。Leaveのときは、opacityを5秒かけて変化させます。
Enterの設定
.transit-enter {
opacity: 0;
}
.transit-enter-from {
opacity: 0;
}
.transit-enter-to {
opacity: 1;
}
Code language: CSS (css)
Enterは、開始時点でopcityはゼロ、終了の時はゼロから1.0に変化する設定にしています。
Leaveの設定
.transit-leave {
opacity: 1;
}
.transit-leave-to {
opacity: 0;
}
Code language: CSS (css)
Leaveha,開始時は1.0で、終了時はゼロです。
3つをセットで考えよう
トランジションのクラスは、Enter/Leaveと各activeの3つがセットになっています。activeのときにtransitionで経過時間を設定し、後はスタート時と終了時にopacityの値を用意します。
イベントを追加
トランジションに用意されているイベント用の属性があります。
Enter関係のイベント
before-enter
Enter開始直前
enter
Enter開始
after-enter
Enter終了後
enter-canselled
Enterキャンセル時
Leave関係のイベント
before-leave
Leave開始直前
leave
Leave開始
after-leave
Leave終了後
leave-canselled
Leaveキャンセル時
これらは<transition>タグにv-onを使って関数などにバインドして設定します。 例えば、v-on:before-enter=”beforeEnter”とすれば、Enter開始直前にbeforeEnter関数が実行されます。
イベントでメッセージを表示する。
<template>
<div class="hello alert alert-primary">
<h2>{{ title }}</h2>
<p>{{ message }}</p>
<hr />
<button class="btn btn-primary m-3" v-on:click="doAction">
{{ btn }}
</button>
<transition
name="transit"
v-on:before-enter="startAction"
v-on:before-leave="startAction"
v-on:after-enter="endAction"
v-on:after-leave="endAction"
>
<p v-if="flg" class="trans alert alert-light h5">Transition!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
title: String,
},
data: function () {
return {
title: "Trans&Anim",
message: "Transition Sample!",
flg: true,
btn: "Hide",
};
},
methods: {
doAction: function () {
this.flg = !this.flg;
},
startAction: function () {
if (this.flg) {
this.message = "現れます.....";
} else {
this.message = "消えます.....";
}
},
endAction: function () {
if (this.flg) {
this.btn = "Hide";
this.message = "現れました。";
} else {
this.btn = "Show";
this.message = "消えました。";
}
},
},
};
</script>
<style>
.trans {
background-color: black;
color: white;
padding: 10px;
font-size: 20pt;
}
.transit-enter-active {
transition: opacity 2s;
}
.transit-leave-active {
transition: opacity 2s;
}
.transit-enter {
opacity: 0;
}
.transit-enter-from {
opacity: 0;
}
.transit-enter-to {
opacity: 1;
}
.transit-leave {
opacity: 1;
}
.transit-leave-to {
opacity: 0;
}
</style>
Code language: HTML, XML (xml)
↑ボタンをクリックすると、「消えます….」とメッセージが変わり、完全に消えたところで「消えました」と表示されます。また、現れるときは、「Show」ボタンを押すとメッセージが「現れます。…..」
transformで動かす
transitionには「transform」という値が用意されており、これを利用することでタグの表示を移動したり、回転したり拡大縮小したりすることができます。↓のように記述します。
transform: ○○ 値;
平行移動
移動幅を示す値を指定します。例えば「100px」。
translateX
横方向に移動
translateY
縦方向に移動
拡大縮小
倍率を示す値を指定します。例えば、「0.5」とすれば半分に縮小し、「2.0」とすると2倍に拡大します。
scale
縦横等倍に拡大縮小
scaleX
横方向に拡大縮小
scaleY
縦方向に拡大縮小
回転
表示要素を時計回りに回転します。角度を示す値を指定します。例えば、「180deg」とすれば、半回転します。
rotateX
X軸を中心に回転
rotateY
Y軸を中心に回転
roteteZ
Z軸を中心に回転
ベースとなる表示を用意
<template>
<div class="alert alert-primary">
<h2>{{ title }}</h2>
<p>{{ message }}</p>
<hr />
<button class="btn btn-primary m-3" v-on:click="doAction">
{{ btn }}
</button>
<transition name="transit">
<p v-if="flg" class="trans">Transition!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: function () {
return {
title: "Trans&Anim",
message: "Transition Sample!",
flg: true,
btn: "Show/Hide",
};
},
methods: {
doAction() {
this.flg = !this.flg;
},
},
};
</script>
<style>
.trans {
background-color: black;
color: white;
padding: 10px;
font-size: 20pt;
}
.transit-enter-active {
transition: 1s;
}
.transit-leave-active {
transition: 1s;
opacity: 0.5;
}
</style>
Code language: HTML, XML (xml)
↑ボタンをクリックするとメッセージがON/OFFされます。transitionに0.1sを指定しているので、1秒をかけて、ON/OFFするようにしてあります。
transformを試してみよう
styleタグ内にtransformを指定したクラスを追加して表示を確認しましょう。
平行移動をする
<template>
<div class="alert alert-primary">
<h2>{{ title }}</h2>
<p>{{ message }}</p>
<hr />
<button class="btn btn-primary m-3" v-on:click="doAction">
{{ btn }}
</button>
<transition name="transit">
<p v-if="flg" class="trans">Transition!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: function () {
return {
title: "Trans&Anim",
message: "Transition Sample!",
flg: true,
btn: "Show/Hide",
};
},
methods: {
doAction() {
this.flg = !this.flg;
},
},
};
</script>
<style>
.trans {
background-color: black;
color: white;
padding: 10px;
font-size: 20pt;
}
.transit-enter-active {
transition: 1s;
}
.transit-leave-active {
transition: 1s;
opacity: 0.5;
}
.transit-enter,
.transit-leave-to {
transform: translateX(200px) translateY(-200px);
opacity: 0.1;
}
</style>
Code language: HTML, XML (xml)
↑ボタンをクリックするとメッセージが右上に移動しながら消えます。
ここではtranslateXとtranslateYを使って、右に200ドット、上に200ドット移動させています。
拡大縮小
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p>{{ message }}</p>
<button class="btn btn-primary mb-3" v-on:click="doAction">
Show/Hide
</button>
<transition name="transit">
<p v-if="flg" class="trans">Transition!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: function () {
return {
title: "Trans&Anim",
message: "Transition Sample!",
flg: true,
btn: "Hide",
};
},
methods: {
doAction() {
this.flg = !this.flg;
},
},
};
</script>
<style>
.trans {
background-color: black;
color: white;
padding: 10px;
font-size: 20pt;
}
.transit-enter-active {
transition: 1s;
}
.transit-leave-active {
transition: 1s;
opacity: 0.5;
}
.transit-enter-from,
.transit-leave-to {
transform: scale(5);
opacity: 0.1;
}
</style>
Code language: HTML, XML (xml)
↑ボタンをクリックすると、メッセージが拡大して消えます。再度クリックすると大きなサイズの状態から次第に縮小し、元のサイズに戻ります。
回転する
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p>{{ message }}</p>
<button class="btn btn-primary mb-3" v-on:click="doAction">
Show/Hide
</button>
<transition name="transit">
<p v-if="flg" class="trans">Transition!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: function () {
return {
title: "Trans&Anim",
message: "Transition Sample!",
flg: true,
btn: "Hide",
};
},
methods: {
doAction() {
this.flg = !this.flg;
},
},
};
</script>
<style>
.trans {
background-color: black;
color: white;
padding: 10px;
font-size: 20pt;
}
.transit-enter-active {
transition: 1s;
}
.transit-leave-active {
transition: 1s;
opacity: 0.5;
}
.transit-enter-from,
.transit-leave-to {
transform: rotateZ(360deg);
opacity: 0.1;
}
</style>
Code language: HTML, XML (xml)
↑ボタンをクリックすると、時計回りにメッセージが回転して消えます。再度クリックすると、逆周りに回転しながら現れます。
degはdegreeのことで、1回転=360で計算した角度になります。
キーフレームによる複雑なアニメーション
animaiton: キーフレーム 経過時間;
このanimationはキーフレームと呼ばれるものを使って要素を動かします。キーフレームは動きの開始から終了までの間に「キー」と呼ばれるものを用意し、各キーの状態に変化しながら動かしていく働きをします。
@keyframes 名前 { 0% { ………開始時の設定……… } ○○% { ………指定したパーセンテージでの状態設定.. } ………必要なだけ用意……. 100% { ……….完了時の設定………. } }
ジグザグに動く
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p>{{ message }}</p>
<button class="btn btn-primary mb-3" v-on:click="doAction">
Show/Hide
</button>
<transition name="transit">
<p v-if="flg" class="trans">Transition!</p>
</transition>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data: function () {
return {
title: "Trans&Anim",
message: "Transition Sample!",
flg: true,
btn: "Hide",
};
},
methods: {
doAction() {
this.flg = !this.flg;
},
},
};
</script>
<style>
.trans {
background-color: black;
color: white;
padding: 10px;
font-size: 20pt;
}
.transit-leave-active {
animation: anim 3s;
}
.transit-enter-active {
animation: anim 2.5s reverse;
}
@keyframes anim {
0% {
transform: translateX(0px) translateY(0px) rotateZ(0deg);
opacity: 1;
background-color: #ddf;
}
25% {
transform: translateX(250px) translateY(0px) rotateZ(0deg);
opacity: 1;
background-color: #fdd;
}
50% {
transform: translateX(0px) translateY(-100px) rotateZ(540deg);
opacity: 1;
background-color: #dfd;
}
75% {
transform: translateX(250px) translateY(-100px) rotateZ(540deg);
opacity: 1;
background-color: #fdf;
}
100% {
transform: translateX(0px) translateY(-200px) rotateZ(1080deg);
opacity: 0;
background-color: #ffd;
}
}
</style>
Code language: HTML, XML (xml)
↑クリックするとメッセージがジグザグに右に左にとジグザグに動きながら、回転したり、背景色を変えたりしてアニメーションします。再度クリックすると逆に再生して元に戻ります。
animationにanimを指定することで、animキーフレームによるアニメーションが行われるようになっています。transit-enter-activeにある「reverse」は逆再生のことです。
*color, font-size, border-widthなどもアニメーションにできます。
ここまで読んでいただいてありがとうございます。
今回はtransitionを使ってのアニメーションのやり方が分かりました。CSSで勉強していたので、頭に入りやすかったです。
掌田津耶乃さんのVue.js3超入門で勉強をしています。語りかけるような文章ですごいわかりやすいです。本当におすすめです。