Here2.click

サブドメインを使用したい方は連絡ください。とかきつつ連絡先書いてないですけど…

vueでカルーセルスライダー

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; }
}
hide

コメントは受け付けていません。