vueでカルーセルスライダー
vue.jsでカルーセルタイプのスライダーを作ってみた。ボタンをクリックすると回転するタイプ。
自動で回り続けるタイプもちょっと改造すれば作れると思う。
v-ifで次に表示される可能性のある要素までは実在させていますが、v-showで全ての要素を実在させておいても良いかと思います。
作りとしては、vueは2でもイケるはず。(コードはvue3)
HTMLは下記の通り
<main> <header> <button type="button" v-on:click="movePanels(1)">1へ</button> <button type="button" v-on:click="movePanels(2)">2へ</button> <button type="button" v-on:click="movePanels(3)">3へ</button> <button type="button" v-on:click="movePanels(4)">4へ</button> <button type="button" v-on:click="movePanels(5)">5へ</button> <button type="button" v-on:click="movePanels(6)">6へ</button> </header> <section id="sec01" v-if="[6, 1, 2].includes(panel) || panel_check < 0" v-bind:class="{'moveLeftPanel':panel == 2, 'moveMiddlePanel':panel == 1, 'moveRightPanel':panel == 6, 'moveMiddle2Right':panel == 1 && panel_next == 6, 'moveMiddle2Left':panel == 1 && panel_next == 2, 'moveRight2Middle':panel == 6 && panel_next == 1, 'moveLeft2Middle':panel == 2 && panel_next == 1}" v-on:animationend="movePanel($event)">A</section> <section id="sec02" v-if="[1, 2, 3].includes(panel) || panel_check < 0" v-bind:class="{'moveLeftPanel':panel == 3, 'moveMiddlePanel':panel == 2, 'moveRightPanel':panel == 1, 'moveMiddle2Right':panel == 2 && panel_next == 1, 'moveMiddle2Left':panel == 2 && panel_next == 3, 'moveRight2Middle':panel == 1 && panel_next == 2, 'moveLeft2Middle':panel == 3 && panel_next == 2}" v-on:animationend="movePanel($event)">B</section> <section id="sec03" v-if="[2, 3, 4].includes(panel) || panel_check < 0" v-bind:class="{'moveLeftPanel':panel == 4, 'moveMiddlePanel':panel == 3, 'moveRightPanel':panel == 2, 'moveMiddle2Right':panel == 3 && panel_next == 2, 'moveMiddle2Left':panel == 3 && panel_next == 4, 'moveRight2Middle':panel == 2 && panel_next == 3, 'moveLeft2Middle':panel == 4 && panel_next == 3}" v-on:animationend="movePanel($event)">C</section> <section id="sec04" v-if="[3, 4, 5].includes(panel) || panel_check < 0" v-bind:class="{'moveLeftPanel':panel == 5, 'moveMiddlePanel':panel == 4, 'moveRightPanel':panel == 3, 'moveMiddle2Right':panel == 4 && panel_next == 3, 'moveMiddle2Left':panel == 4 && panel_next == 5, 'moveRight2Middle':panel == 3 && panel_next == 4, 'moveLeft2Middle':panel == 5 && panel_next == 4}" v-on:animationend="movePanel($event)">D</section> <section id="sec05" v-if="[4, 5, 6].includes(panel) || panel_check < 0" v-bind:class="{'moveLeftPanel':panel == 6, 'moveMiddlePanel':panel == 5, 'moveRightPanel':panel == 4, 'moveMiddle2Right':panel == 5 && panel_next == 4, 'moveMiddle2Left':panel == 5 && panel_next == 6, 'moveRight2Middle':panel == 4 && panel_next == 5, 'moveLeft2Middle':panel == 6 && panel_next == 5}" v-on:animationend="movePanel($event)">E</section> <section id="sec06" v-if="[5, 6, 1].includes(panel) || panel_check < 0" v-bind:class="{'moveLeftPanel':panel == 1, 'moveMiddlePanel':panel == 6, 'moveRightPanel':panel == 1, 'moveMiddle2Right':panel == 6 && panel_next == 5, 'moveMiddle2Left':panel == 6 && panel_next == 1, 'moveRight2Middle':panel == 5 && panel_next == 6, 'moveLeft2Middle':panel == 1 && panel_next == 6}" v-on:animationend="movePanel($event)">F</section> </main>
JSは下記の通り
<script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'; const vueApp = createApp({ data() { return { panel: 1, panel_next: 0, panel_target: 0, panel_direction: 0, panel_check: -1, } }, mounted() { this.panel_check = document.querySelectorAll('main section').length; }, methods: { movePanels: function(targetPanel, event){ let interval = Math.abs(targetPanel - this.panel); let chk1 = ( targetPanel > this.panel ) ? 1 : -1; let chk2 = ( interval > (this.panel_check / 2) ) ? -1 : 1; this.direction = chk1 * chk2; this.panel_next = (this.panel + this.direction == 0 || this.panel + this.direction == this.panel_check) ? this.panel_check : (this.panel + this.direction) % this.panel_check; this.panel_target = targetPanel; }, movePanel: function(event){ for(let className of event.currentTarget.classList){ if( ['moveRight2Middle', 'moveLeft2Middle'].includes(className) ){ this.panel = this.panel_next != 0 ? this.panel_next : this.panel; if( this.panel_next == this.panel_target ){ this.panel_target = 0; this.panel_next = 0; } else{ this.panel_next = (this.panel + this.direction == 0 || this.panel + this.direction == this.panel_check) ? this.panel_check : (this.panel + this.direction) % this.panel_check; } }; }; }, }, }).mount('main'); </script>
CSS(SCSS)は下記の通り
header { width: 100vw; position: fixed; top: 0; left: 0; display: flex; z-index: 10; } main { width: 100vw; height: 100vh; overflow-x: hidden; position: relative; section { width: 100vw; min-width: 100vw; height: 100vh; sec01 { background-color: bisque; } sec02 { background-color: paleturquoise; } sec03 { background-color: plum; } sec04 { background-color: honeydew; } sec05 { background-color: plum; } sec06 { background-color: coral; } } } .moveLeftPanel { position: absolute; left: -100vw; } .moveMiddlePanel { position: absolute; left: 0; } .moveRightPanel { position: absolute; left: 100vw; } .moveRight2Middle { animation-name: rigth2middle; animation-duration: 0.2s; animation-timing-function: ease-in-out; } .moveLeft2Middle { animation-name: left2middle; animation-duration: 0.2s; animation-timing-function: ease-in-out; } .moveMiddle2Right { animation-name: middle2rigth; animation-duration: 0.2s; animation-timing-function: ease-in-out; } .moveMiddle2left { animation-name: middle2left; animation-duration: 0.2s; animation-timing-function: ease-in-out; } @keyframes rigth2middle { 0% { left: 100vw; } 100% { left: 0; } } @keyframes left2middle { 0% { left: -100vw; } 100% { left: 0; } } @keyframes middle2rigth { 0% { left: 0; } 100% { left: 100vw; } } @keyframes middle2left { 0% { left: 0; } 100% { left: -100vw; } }