LoginSignup
1
1

More than 1 year has passed since last update.

Vue3系でフェードアニメーション

Posted at

これは何?

画像がフェードイン&フェードアウトするサンプル。

作った経緯

勉強のため。
かつ、ネットには動かないサンプルが大量に転がっていて腹がたったから。

今回重視したのは以下2つです。

  • v-forv-if を同時に使いたい時にどうするか理解する
  • transition によるアニメーション挙動を理解する

そもそも、v-forv-if を同時に使うことは非推奨だとドキュメントに書いてあるのに、
ネットでは同時に使っているサンプルが出てくるので、ドキュメントのことを思い出すまでに時間がかかりました。

スタイリングガイドによると、要は

  • フィルタ済みの Object で for を回す
  • template 構文を使って、 for と if を分ける
    このどちらかにしなければいけないので、今回は後者を選びました。

コード

<template>
	<div class="slider-outer">
		<div class="slider-inner">
			<template v-for="(slide, idx) in slides" :key="idx">
				<transition name="fade" mode="in-out">
					<img v-if="idx == currentSlide" v-bind:src="slide.img" width="450" height="300">
				</transition>
			</template>
		</div>
		<div class="slider-trigger">
			<button class="prev" v-on:click="prev()"> &lt; </button>
			<button class="next" v-on:click="next()"> &gt; </button>
		</div>
	</div>
</template>

<script>
export default {
	data: function(){
		return({
			currentSlide: 0,
			timerId: 0,
			slides: [
				{ img: require('./assets/img1.jpg') },
				{ img: require('./assets/img2.jpg') },
				{ img: require('./assets/img3.jpg') },
				{ img: require('./assets/img4.jpg') },
			],
		})
	},
	created: function(){
		setTimeout(this.autoPlay, 3 * 1000);
	},
	methods: {
		prev: function(){
			this.currentSlide--;
			if(this.currentSlide == -1){
				this.currentSlide = this.slides.length -1;
			}
			this.cancelTimer();
			this.autoPlay();
		},
		next: function(){
			this.currentSlide++;
			if(this.currentSlide == this.slides.length){
				this.currentSlide = 0;
			}
			this.cancelTimer();
			this.autoPlay();
		},
		autoPlay: function(){
			this.currentSlide++;
			if(this.currentSlide == this.slides.length){
				this.currentSlide = 0;
			}
			this.timerId = setTimeout(this.autoPlay, 3 * 1000);
		},
		cancelTimer: function() {
			clearTimeout(this.timerId);
		}
	},
}
</script>

<style lang="scss">
*, *:before, *:after {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}
.slider-outer{
	position: relative;
	width: 100%;
	height: 600px;
	overflow: hidden;
	margin: 0;
}
.slider-inner{
	position: relative;
	width: 100%;
	height: 100%;
	background-color: #222222;
	img {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		display: block;
		width: 100%;
		height: auto;
	}
}
.slider-trigger{
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 100%;
	z-index: 10;
	button {
		position: absolute;
		background-color: transparent;
		border: none;
		cursor: pointer;
		outline: none;
		padding: 0;
		appearance: none;
		font-size: 24px;
		color: #FFFFFF;
	}
	.next { right: 30px; }
	.prev { left:  30px; }
}
.fade-enter-active {
	transition: all 1s ease;
	position: absolute;
	z-index: 2;
}
.fade-leave-active {
	transition: all 1s ease;
	position: absolute;
	z-index: 3;
}
.fade-enter    { opacity: 0; }
.fade-leave-to { opacity: 0; }
</style>

最後に

次回からは先にドキュメントとスタイルガイドを読むことにします。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1