UNPKG

kui-vue

Version:

A high quality UI Toolkit built on Vue.js 2.0

148 lines (143 loc) 3.4 kB
import Icon from "../icon"; import resize from '../_tool/resize' import { getChild } from '../_tool/utils' import { ChevronUp } from 'kui-icons' export default { name: 'Carousel', directives: { resize }, props: { value: { type: Number, default: 0 }, loop: Boolean, autoplay: Boolean, delay: { type: Number, default: 3000 }, vertical: Boolean, dots: { type: Boolean, default: true } }, data() { return { currentIndex: this.value, autotimer: null, width: 0, height: 0, animate: this.value > 0 ? false : true, resizing: false, playing: false, } }, provide() { return { Carousel: this } }, watch: { value(v) { this.currentIndex = v }, }, beforeDestroy() { clearInterval(this.autotimer) }, methods: { next() { this.change('right') }, prev() { this.change('left') }, autoToPlay() { clearInterval(this.autotimer) this.autotimer = setInterval(() => { this.change('right') }, parseInt(this.delay)); }, change(type) { if (this.playing) return; this.animate = true let index = this.currentIndex if (type == 'left') { index -= 1 index = Math.max(0, index) } else if (type == 'right') { let length = getChild(this.$slots.default).length if (!this.loop) { if (index == length - 1) { index = 0 } else index += 1 index = Math.min(length - 1, index) } } else { index = type } this.currentIndex = index this.playing = true setTimeout(() => { this.playing = false }, 600); }, resize() { this.animate = false let carousel = this.$refs.carousel this.width = carousel.offsetWidth this.height = carousel.offsetHeight } }, mounted() { this.$nextTick(e => { this.resize() this.autoplay && this.autoToPlay() }) }, render() { let { currentIndex, change, vertical } = this let childs = getChild(this.$slots.default) currentIndex = Math.min(childs.length - 1, currentIndex) currentIndex = Math.max(0, currentIndex) const classes = ['k-carousel', { 'k-carousel-vertical': vertical }] const dotsNode = ( <ul class="k-carousel-dots"> {childs.map((e, i) => <li class={{ 'k-carousel-dots-active': currentIndex == i }} onClick={e => change(i)}></li>)} </ul> ) let offsetX = 0, offsetY = 0; if (!vertical) { offsetX = currentIndex * this.width } else { offsetY = currentIndex * this.height } const warpperCls = { class: 'k-carousel-warpper', style: { transform: `translateX(-${offsetX}px) translateY(-${offsetY}px)`, width: !vertical ? childs.length * this.width + 'px' : '', height: vertical ? childs.length * this.height + 'px' : '', transitionDuration: !this.animate ? '0s' : '' } } const arrowLeft = <span class="k-carousel-arrow-left" onClick={e => change('left')}> <Icon type={ChevronUp} /> </span> const arrowRight = <span class="k-carousel-arrow-right" onClick={e => change('right')}> <Icon type={ChevronUp} /> </span> const props = { class: classes, ref: 'carousel', on: { mouseenter: e => clearInterval(this.autotimer), mouseleave: e => { this.autoplay && this.autoToPlay() } } } return ( <div v-resize={this.resize} {...props}> <div {...warpperCls}> {childs} </div> {!vertical ? [arrowLeft, arrowRight] : null} {this.dots ? dotsNode : null} </div > ) } }