UNPKG

vue-carousel

Version:

A flexible, responsive, touch-friendly carousel for Vue.js

735 lines (727 loc) 24 kB
/* eslint-disable */ import Vue from "vue" import { play } from "vue-play" import Carousel from "../src/Carousel.vue" import Slide from "../src/Slide.vue" const containerWidth = 500; const images = [ "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176006_1.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176005_2.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176003_3.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176004_4.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176002_5.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176001_2.jpg" ] const LargeAmountImages = [ "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176006_1.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176005_2.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176003_3.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176004_4.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176002_5.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176001_2.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176004_4.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176002_5.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176001_2.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176004_4.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176002_5.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176001_2.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176001_2.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176004_4.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176002_5.jpg", "https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176001_2.jpg" ] const generateSlideImages = (createElement) => images.map((image) => createElement(Slide, {}, [ createElement( "img", { style: { width: "100%" }, attrs: { src: image } } ) ]) ) const createContainer = (createElement, width, content) => createElement( 'div', { style: { width: '100%', display: 'flex', justifyContent: 'center', marginTop: '40px' } }, [ createElement( 'div', { style: { width: `${width}px` } }, content ) ] ) play("Carousel", module) .add("Default", h => createContainer( h, containerWidth, [h(Carousel, {}, generateSlideImages(h))] ) ) .add("Too few per page", h => createContainer( h, containerWidth, [h(Carousel, { props: { perPage: 10, scrollPerPage: false } }, generateSlideImages(h))] ) ) .add("3 per page", h => createContainer( h, containerWidth, [h(Carousel, { props: { perPage: 3 } }, generateSlideImages(h))] ) ) .add("Scroll per page false", h => createContainer( h, containerWidth, [h(Carousel, { props: { scrollPerPage: false } }, generateSlideImages(h))] ) ) .add("Responsive", h => createContainer( h, containerWidth, [h(Carousel, { props: { perPageCustom: [[480, 3], [768, 4]] } }, generateSlideImages(h))] ) ) .add("Center and hide navigation", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel :per-page-custom="[[480, 1], [768, 4]]" :center-mode="true" :navigation-enabled="true" style="width: 500px;"> <slide v-for="slide in slideCount"> <img style="width: 100%;" src="https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176006_1.jpg" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slideCount: 3 } } }) .add("Autoplay", h => createContainer( h, containerWidth, [h(Carousel, { props: { autoplay: true, autoplayHoverPause: false } }, generateSlideImages(h))] ) ) .add("Autoplay, navigation", h => createContainer( h, containerWidth, [h(Carousel, { props: { autoplay: true, autoplayHoverPause: false , navigationEnabled: true} }, generateSlideImages(h))] ) ).add("Autoplay, Looping", h => createContainer( h, containerWidth, [h(Carousel, { props: { autoplay: true, autoplayHoverPause: false, loop: true } }, generateSlideImages(h))] ) ) .add("Autoplay, pause on hover", h => createContainer( h, containerWidth, [h(Carousel, { props: { autoplay: true, autoplayHoverPause: true } }, generateSlideImages(h))] ) ) .add("Autoplay, Pause/Resume", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" :autoplay="autoplay" :loop="true"> <slide v-for="slide in slideCount" :key="slide"> <img style="width: 100%;" src="https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176006_1.jpg" /> </slide> </carousel> <div style="float: left"> <pre>Autoplay Status: {{ autoplay }}</pre> <button v-on:click="toggleAutoplay()">Toggle Autoplay</button> </div> </div>`, components: { Carousel, Slide }, data() { return { autoplay: true, slideCount: 8 } }, methods: { toggleAutoplay() { this.autoplay = !this.autoplay; }, } }) .add("Dynamic, add or remove slides", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;"> <slide v-for="slide in slideCount" :key="slide"> <img style="width: 100%;" src="https://res.cloudinary.com/ssenseweb/image/upload/b_white,c_lpad,g_south,h_1086,w_724/c_scale,h_560/v588/171924M176006_1.jpg" /> </slide> </carousel> <div style="float: left"> <button v-on:click="addSlide">Add slide</button> <button v-on:click="removeSlide">Remove slide</button> </div> </div>`, components: { Carousel, Slide }, data() { return { slideCount: 4 } }, methods: { addSlide() { this.slideCount++ }, removeSlide() { if (this.slideCount > 1) { this.slideCount-- } } } }) .add("With navigation buttons", h => createContainer( h, containerWidth, [h(Carousel, { props: { navigationEnabled: true } }, generateSlideImages(h))] ) ) .add("Navigation buttons and scrollPerPage false", h => createContainer( h, containerWidth, [h(Carousel, { props: { navigationEnabled: true, scrollPerPage: false } }, generateSlideImages(h))] ) ) .add("Navigation buttons and scrollPerPage false and loop", h => createContainer( h, containerWidth, [h(Carousel, { props: { navigationEnabled: true, scrollPerPage: false, loop: true } }, generateSlideImages(h))] ) ) .add("With customized navigation buttons", h => createContainer( h, containerWidth, [h('style', '.VueCarousel-navigation-button { font-size: 36px; }'), h(Carousel, { props: { paginationColor: '#fac232', paginationActiveColor: '#c9750c', navigationEnabled: true, navigationNextLabel: '👉', navigationPrevLabel: '👈' } }, generateSlideImages(h))] ) ) .add("navigation-click event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @navigation-click="onNavigationClick" navigationEnabled :paginationEnabled="false"> <slide v-for="slide in slides" :key="slide"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onNavigationClick(direction) { this.$log(`Captured [navigation-click] event. Current direction is ${direction}`) }, } }) .add("pagination-click event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @pagination-click="onPaginationClick"> <slide v-for="slide in slides" :key="slide"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onPaginationClick (currentPage) { this.$log(`Captured [pagination-click] event. Current page is ${currentPage}`) }, } }) .add("With local event on pageChange", { .add("navigation-click event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @navigation-click="onNavigationClick" navigationEnabled :paginationEnabled="false"> <slide v-for="slide in slides" :key="slide"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onNavigationClick(direction) { this.$log(`Captured [navigation-click] event. Current direction is ${direction}`) }, } }) .add("pagination-click event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @pagination-click="onPaginationClick"> <slide v-for="slide in slides" :key="slide"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onPaginationClick (currentPage) { this.$log(`Captured [pagination-click] event. Current page is ${currentPage}`) }, } }) .add("With local event on pageChange", { .add("pageChange event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @pageChange="onPageChange"> <slide v-for="slide in slides" :key="slide"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onPageChange(currentPage) { this.$log(`Captured [pageChange] event. Current page is ${currentPage}`) }, } }) .add("slideclick event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;"> <slide v-for="slide in slides" :key="slide" @slideclick="onSlideClick"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onSlideClick(currentDataset) { this.$log(`Captured [slideclick] event. Current dataset is ${JSON.stringify(currentDataset)}`) }, } }) .add("slide-click event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;"> <slide v-for="slide in slides" :key="slide" @slide-click="onSlideClick"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onSlideClick(currentDataset) { this.$log(`Captured [slide-click] event. Current dataset is ${JSON.stringify(currentDataset)}`) }, } }) .add("page-change event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @page-change="onPageChange"> <slide v-for="slide in slides" :key="slide"> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } }, methods: { onPageChange(currentPage) { this.$log(`Captured [page-change] event. Current page is ${currentPage}`) }, } }) .add("NavigateTo pages", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" :navigateTo="newPage" v-on:pagechange="pageChanged"> <slide v-for="slide in slides" :key="slide"> <img style="width: 100%;" :src= slide /> </slide> </carousel> <div style="float: left; z-index: 1000"> <button style="position: absolute; bottom: 20px; right: 250px" v-on:click="gotoPage(0)">Goto page 1</button> <button style="position: absolute; bottom: 20px; right: 150px" v-on:click="gotoPage(1)">Goto page 2</button> <button style="position: absolute; bottom: 20px; right: 50px" v-on:click="gotoPage(2)">Goto page 3</button> </div> </div>`, components: { Carousel, Slide }, data(){ return { newPage:0, slides: images } }, methods: { gotoPage(val) { this.newPage = val; }, pageChanged(val) { this.newSlide = val; } } }) .add("NavigateTo slides", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" :navigateTo="navigateTo" :scrollPerPage=false v-on:pagechange="pageChanged"> <carousel style="width: 500px;" :navigateTo="newSlide" :scrollPerPage=false v-on:pagechange="pageChanged"> <carousel style="width: 500px;" :navigateTo="navigateTo" :scrollPerPage=false v-on:pagechange="pageChanged"> <slide v-for="slide in slides" :key="slide.src"> <img style="width: 100%;" :src= slide /> </slide> </carousel> <div style="float: left; z-index: 1000"> <button style="position: absolute; bottom: 20px; right: 350px" v-on:click="gotoSlide(0)">Goto slide 1</button> <button style="position: absolute; bottom: 20px; right: 250px" v-on:click="gotoSlide(1)">Goto slide 2</button> <button style="position: absolute; bottom: 20px; right: 50px" v-on:click="gotoSlide(4, false)">Goto slide 5 without animation</button> </div> </div>`, components: { Carousel, Slide }, data(){ return { newSlide: 0, newSlideAnimation: true, slides: images } }, computed: { navigateTo() { if (this.newSlideAnimation) return this.newSlide else return [this.newSlide, false] } }, methods: { gotoSlide(val, animation) { this.newSlideAnimation = (animation === false ? false : true); this.newSlide = val; }, pageChanged(val) { this.newSlide = val; } } }) .add("With spacePadding 100px", h => createContainer( h, containerWidth, [h(Carousel, { props: { spacePadding: 100, perPage: 1} }, generateSlideImages(h))] ) ) .add("transitionStart event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @transitionStart="handleTransitionStart" > <slide v-for="slide in slides" :key="slide.src"> <img style="width: 100%;" :src= slide /> </slide> </carousel> </div>`, data() { return { slides: images } }, components: { Carousel, Slide }, methods: { handleTransitionStart() { this.$log('Captured [transitionStart] event') } } }) .add("transition-start event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @transition-start="handleTransitionStart" > <slide v-for="slide in slides" :key="slide.src"> <img style="width: 100%;" :src= slide /> </slide> </carousel> </div>`, data() { return { slides: images } }, components: { Carousel, Slide }, methods: { handleTransitionStart() { this.$log('Captured [transition-start] event') } } }) .add("transitionEnd event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @transitionEnd="handleTransitionEnd" > <slide v-for="slide in slides" :key="slide.src"> <img style="width: 100%;" :src= slide /> </slide> </carousel> </div>`, data() { return { slides: images } }, components: { Carousel, Slide }, methods: { handleTransitionEnd() { this.$log('Captured [transitionEnd] event') } } }) .add("transition-end event", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" @transition-end="handleTransitionEnd" > <slide v-for="slide in slides" :key="slide.src"> <img style="width: 100%;" :src= slide /> </slide> </carousel> </div>`, data() { return { slides: images } }, components: { Carousel, Slide }, methods: { handleTransitionEnd() { this.$log('Captured [transition-end] event') } } }) .add("Custom width", { components: { Carousel, Slide }, render: h => { return createContainer( h, containerWidth, [h(Carousel, { props: { perPage: 1, spacePadding: 30 } }, [new Array(8).fill(0).map((item, index) => { return h(Slide, {}, [h("div", { style: { width: "100%", height: "400px", lineHeight: "400px", color: "#fff", textAlign: "center", fontSize: "30px", backgroundColor: (index % 2 === 0) ? "#42b983" : "#ff3c3c" } }, [index])]) })])] ) } }) .add("Emit selected element dataset", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;" :navigateTo="newSlide" :scrollPerPage=false> <slide v-for="(slide, index) in slides" :key="slide.src" :data-index="index" v-on:slideclick="onSlideClick"> <img style="width: 100%;" :src= slide /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data(){ return { newSlide: 0, slides: images } }, methods: { onSlideClick (data) { this.$log(data) } } }) .add("Get and set current Page with v-model", { template: ` <div> <div style="text-align: center;"> <input type="number" v-model="currentPage" style="text-align: center; font-size: 3em; width: 100px;"> </div> <div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 300px;" v-model="currentPage" :perPage="1" > <slide v-for="slide in slides" :key="slide.src"> <img style="width: 100%;" :src= slide /> </slide> </carousel> </div> </div>`, data() { return { currentPage: 0, slides: images } }, components: { Carousel, Slide }, methods: { } }) .add("With adjustableHeight", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 300px;" :adjustableHeight="true" :navigationEnabled="true" :perPage="1"> <slide v-for="(slide, idx) in slides"> <div style="width: 300px;"> <img :style="'height: ' + ((idx + 1) * 50) + 'px;'" :src="slide" /> </div> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } } }) .add("Pagination position top", h => createContainer( h, containerWidth, [h(Carousel, { props: { paginationPosition: 'top' } }, generateSlideImages(h))] )) .add("Pagination position top-overlay", h => createContainer( h, containerWidth, [h(Carousel, { props: { paginationPosition: 'top-overlay' } }, generateSlideImages(h))] )) .add("Pagination position bottom-overlay", h => createContainer( h, containerWidth, [h(Carousel, { props: { paginationPosition: 'bottom-overlay' } }, generateSlideImages(h))] )) .add("With custom pagination titles", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px;"> <slide v-for="(slide, index) in slides" :key="slide" :title="'This is my slide #' + index "> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: images } } }) .add("With custom pagination dot number", { template: `<div style="width: 100%; display: flex; justify-content: center; margin-top: 40px;"> <carousel style="width: 500px" :maxPaginationDotCount="5" :perPage="1"> <slide v-for="(slide, index) in slides" :key="slide" :title="'This is my slide #' + index "> <img style="width: 100%;" :src="slide" /> </slide> </carousel> </div>`, components: { Carousel, Slide }, data() { return { slides: LargeAmountImages } } })