
Vue.jsでレスポンシブに対応したシンプルなカルーセルを作成してみる
ウェブサイトのUIでよく見かけるカルーセル型のコンテンツですが、いろんなプラグインも登場しており手軽に導入することも可能です。その中にはVue.jsで出来ているものもいくつかあり、Vue.jsのプロジェクトにおいても「Vue Carousel」というプラグインはよく使われているようです。ただ、Lighthouseのスコアで減点となる項目があったり、細かい部分の調整やカスタマイズもしてみたいと思い、練習も兼ねてVue.jsでカルーセルを作成してみました。
今回はレスポンシブ対応のカルーセルで、オートプレイ機能とページャーがついたシンプルなものになります。一応ループ再生に対応していますが、最後のアイテムまで表示されると最初の表示位置に戻るというようなかたちになっています。レスポンシブ対応である今回のカルーセルで必要となる情報ですが、全てのカルーセルアイテムを並べた横幅とカルーセルアイテムの総数、そして1つあたりのカルーセルの横幅、そして現在表示されている先頭のカルーセルアイテムの順番となります。これらを変数としてVue.jsの中で扱っていきます。
それでは実際のコードをみていきます。まずはHTMLからです、今回はPugを使っています。始めにカルーセル部分の全体を囲うラッパー要素を作成します。ここでは.carousel-wrapperとしています。その中にカルーセル本体とページャー用のボタン要素を配置しています。カルーセル本体の要素はVue側でDOMから要素の幅を取得する必要があるので、ref属性で紐づけられるようにします。その中にはカルーセルアイテムとなる要素を繰り返していきますが、Vueのdataオプションで定義した配列を展開するようにしておきますので、v-forディレクティブで繰り返すようにします。その時にポイントとなるのがカルーセルアイテムの幅が変数で設定できるようにしておくことです。こうすることでウィンドウリサイズ時にも適切な幅に可変できるようになっています。
【HTML(Pug)】
より複雑な動きやいろんな要件に合わせるためにはもう少し改良の余地はありそうですが、、とりあえずシンプルな動きのもので間に合うようでしたらこのようなものでも十分なのではないでしょうか。プラグインの利用もいいですが、必要に合わせて自前で用意できるようにもしておきたいものですね。
div.carousel-wrapper#app
div(class="carousel-inner" ref="carousel_inner")
div(v-for="(item, index) in carousel" :key="index" class="carousel-item" :style="`width: ${itemWidth}px`")
span {{ item.name }}
button(@click="prev()" class="prev") Prev
button(@click="next()" class="next") Next
上記では、カルーセル内にテキストが入る形となっていますが、画像を配置させることももちろん可能です。続いてCSSでカルーセルの配置を整えていきます。まず全体の要素には、overflow: hidden;を設定し、ページャーを自由に配置できるようposition: relative;を設定しておきます。これでページャーにposition: absolute;を指定することでカルーセルエリア合わせてレイアウトができるようになります。
【CSS(SASS)】
.carousel-wrapper
overflow: hidden
position: relative
.carousel-inner
width: 100%
display: flex
justify-content: space-between
flex-wrap: nowrap
transition: all 1.2s ease-out 0s
.carousel-item
flex-shrink: 0
button
position: absolute
top: 50%
transform: translateY(-50%)
&.prev
left: 0
&.next
right: 0
カルーセルアイテムはここではFlexboxで横に並べています。折り返し指定で行内に収まるようにし、フレックスアイテム要素には、flex-shrink: 0;を指定することで正しくカルーセルの幅が反映されるようになります。これでカルーセル自体のレイアウトができましたので、あとはJavaScriptで動かしていきます。
今回はVue.jsを使ってカルーセルの動きの部分を作っていきます。Vueインスタンスを作成し、カルーセル全体のラッパー要素にマウントさせていきます。dataオプションではカルーセルアイテムの要素を定義し、合わせてカルーセルアイテムの幅、一度に表示させるアイテム数、現在の先頭アイテムのインデックス、そして回転を止めておく時間を初期値として定義します。続いてcomputedオプションでカルーセルアイテムの総数とカルーセルを移動する距離を算出できるようにしておきます。
【JavaScript(Vue)】
const vueModel = new Vue({
el: '#app',
data() {
return {
carousel: [
{ name: 'カルーセル1' }, { name: 'カルーセル2' }, { name: 'カルーセル3' }, { name: 'カルーセル4' }
],
itemWidth: 0,
showPerView: 3,
currentItem: 1,
delay: 3000
}
},
computed: {
countItems() {
return this.carousel.length + 1;
},
slideLength() {
return this.itemWidth * this.currentItem
}
},
mounted() {
window.addEventListener('load', () => {
this.init();
});
window.addEventListener('resize', () => {
this.init();
});
this.start();
},
methods: {
init() {
this.itemWidth = this.$refs.carousel_inner.clientWidth / this.showPerView;
},
slide() {
this.$refs.carousel_inner.style.transform = `translateX(-${this.slideLength}px)`;
},
start() {
setInterval(() => {
if (this.countItems - this.showPerView - 1 >= this.currentItem) {
this.slide();
this.currentItem++;
} else {
this.$refs.carousel_inner.style.transform = `translateX(0)`;
this.currentItem = 1;
}
}, this.delay)
},
prev() {
if (0 < this.currentItem) {
this.currentItem = this.currentItem - 1;
this.slide();
}
},
next() {
if (this.countItems - this.showPerView - 1 > this.currentItem) {
this.currentItem = this.currentItem + 1;
this.slide();
}
}
}
});
続いてmethodsオプションでは、カルーセルアイテムの幅をリセットする関数と、カルーセルを動かす関数、そして一定時間ごとに回転を繰り返す関数とページャーをクリックした時の処理を定義します。ポイントとなるのは、setIntervalで繰り返し処理を行うのですが、この時に毎回現在の先頭アイテムのインデックスを更新していくようにします。こうすることでアイテムに合わせた回転が行われるようになります。
最後にmountedのオプションで回転を繰り返す関数と、リサイズと読み込み完了時にカルーセルアイテムの幅をリセットする関数を実行するようにしておきます。合わせてページャーのクリックイベントでページャー処理の関数が実行できるように設定しておきましょう。これでカルーセルの要素が出来上がりました。今回のサンプルはこちらで確認することができます。
See the Pen responsive-carousel_on_vue by designsupply (@designsupply) on CodePen.
より複雑な動きやいろんな要件に合わせるためにはもう少し改良の余地はありそうですが、、とりあえずシンプルな動きのもので間に合うようでしたらこのようなものでも十分なのではないでしょうか。プラグインの利用もいいですが、必要に合わせて自前で用意できるようにもしておきたいものですね。
categories
- WordPress(61)
- JavaScript(49)
- Vue.js(48)
- CSS(46)
- jQuery(34)
- Nuxt.js(22)
- Sass(21)
- Gulp(17)
- webpack(16)
- PHP(14)
- HTML(14)
- GSAP(11)
- React(10)
- Vite(9)
- Pug(9)
- Laravel(8)
- Cordova(8)
- Linux(7)
- Next.js(6)
- Apache(5)
- Shopify(4)
- REST API(4)
- Node.js(4)
- Smarty(3)
- Git(3)
- JSON(3)
- その他プログラミング(3)
- Google Apps API(3)
- Bootstrap(3)
- 環境構築・システム(3)
- TypeScript(2)
- EJS(2)
- RMS(2)
- Docker(2)
- Instagram API(2)
- Excel VBA(2)
- SVG(1)
- Dart(1)
- ECカートASP(1)
- Markdown(1)
- AMP(1)
- Nginx(1)
- XML(1)
- shellscript(1)
- Ruby(1)
- MySQL(1)