2017-01-16 02:45:11 -06:00
|
|
|
<template>
|
2017-01-16 02:59:46 -06:00
|
|
|
<div :class="classes">
|
2017-01-17 14:29:51 -06:00
|
|
|
<button :class="arrowClasses" class="left" @click="add(-1)">
|
|
|
|
<Icon type="chevron-left"></Icon>
|
|
|
|
</button>
|
2017-01-16 04:00:52 -06:00
|
|
|
<div :class="[prefixCls + '-list']">
|
|
|
|
<div :class="[prefixCls + '-track']" :style="trackStyles" v-el:slides>
|
|
|
|
<!-- opacity: 1; width: 4480px; transform: translate3d(-1120px, 0px, 0px); -->
|
|
|
|
<slot></slot>
|
|
|
|
</div>
|
|
|
|
</div>
|
2017-01-17 14:29:51 -06:00
|
|
|
<button :class="arrowClasses" class="right" @click="add(1)">
|
|
|
|
<Icon type="chevron-right"></Icon>
|
|
|
|
</button>
|
|
|
|
<ul :class="dotsClasses">
|
|
|
|
<template v-for="n in slides.length">
|
|
|
|
<li :class="{ [`${prefixCls}-active`]: n === currentIndex }"
|
|
|
|
@click="dotsEvent('click', n)"
|
|
|
|
@mouseover="dotsEvent('hover', n)">
|
|
|
|
<button></button>
|
|
|
|
</li>
|
|
|
|
</template>
|
|
|
|
</ul>
|
2017-01-16 02:45:11 -06:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script>
|
2017-01-16 02:59:46 -06:00
|
|
|
import Icon from '../icon/icon.vue';
|
2017-01-16 04:00:52 -06:00
|
|
|
import { oneOf, getStyle, deepCopy, getScrollBarSize } from '../../utils/assist';
|
2017-01-16 02:59:46 -06:00
|
|
|
|
|
|
|
const prefixCls = 'ivu-carousel';
|
2017-01-16 02:45:11 -06:00
|
|
|
|
|
|
|
export default {
|
2017-01-16 02:59:46 -06:00
|
|
|
name: 'Carousel',
|
|
|
|
props: {
|
2017-01-17 14:29:51 -06:00
|
|
|
arrow: {
|
|
|
|
type: String,
|
|
|
|
default: 'hover'
|
2017-01-16 02:59:46 -06:00
|
|
|
},
|
|
|
|
autoplay: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true
|
|
|
|
},
|
|
|
|
autoplaySpeed: {
|
|
|
|
type: Number,
|
|
|
|
default: 2000
|
|
|
|
},
|
|
|
|
easing: {
|
|
|
|
type: String,
|
|
|
|
default: 'ease'
|
|
|
|
},
|
|
|
|
dots: {
|
2017-01-17 14:29:51 -06:00
|
|
|
type: String,
|
|
|
|
default: 'inside'
|
|
|
|
},
|
|
|
|
trigger: {
|
|
|
|
type: String,
|
|
|
|
default: 'click'
|
2017-01-16 02:59:46 -06:00
|
|
|
},
|
|
|
|
vertical: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
2017-01-16 04:12:46 -06:00
|
|
|
},
|
|
|
|
currentIndex: {
|
|
|
|
type: Number,
|
|
|
|
default: 0
|
2017-01-16 02:59:46 -06:00
|
|
|
}
|
|
|
|
},
|
2017-01-16 04:00:52 -06:00
|
|
|
data () {
|
|
|
|
return {
|
|
|
|
prefixCls: prefixCls,
|
|
|
|
listWidth: 0,
|
|
|
|
trackWidth: 0,
|
2017-01-16 04:12:46 -06:00
|
|
|
trackLeft: 0,
|
2017-01-16 04:00:52 -06:00
|
|
|
slides: [],
|
2017-01-16 04:12:46 -06:00
|
|
|
slideInstances: [],
|
|
|
|
timer: null
|
2017-01-16 04:00:52 -06:00
|
|
|
}
|
|
|
|
},
|
2017-01-16 02:59:46 -06:00
|
|
|
computed: {
|
|
|
|
classes () {
|
|
|
|
return [
|
|
|
|
`${prefixCls}`,
|
|
|
|
{
|
|
|
|
[`${prefixCls}-vertical`]: this.vertical
|
|
|
|
}
|
|
|
|
];
|
2017-01-16 04:00:52 -06:00
|
|
|
},
|
|
|
|
trackStyles () {
|
|
|
|
return {
|
2017-01-16 04:12:46 -06:00
|
|
|
width: `${this.trackWidth}px`,
|
|
|
|
transform: `translate3d(-${this.trackLeft}px, 0px, 0px)`,
|
|
|
|
transition: `transform 500ms ${this.easing}`
|
2017-01-16 04:00:52 -06:00
|
|
|
};
|
2017-01-17 14:29:51 -06:00
|
|
|
},
|
|
|
|
arrowClasses () {
|
|
|
|
return [
|
|
|
|
`${prefixCls}-arrow`,
|
|
|
|
`${prefixCls}-arrow-${this.arrow}`
|
|
|
|
]
|
|
|
|
},
|
|
|
|
dotsClasses () {
|
|
|
|
return [
|
|
|
|
`${prefixCls}-dots`,
|
|
|
|
`${prefixCls}-arrow-${this.dots}`
|
|
|
|
]
|
|
|
|
},
|
|
|
|
activeDot (n) {
|
|
|
|
return {
|
|
|
|
[`${prefixCls}-vertical`]: this.currentIndex === n
|
|
|
|
}
|
2017-01-16 04:00:52 -06:00
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
// find option component
|
|
|
|
findChild (cb) {
|
|
|
|
const find = function (child) {
|
|
|
|
const name = child.$options.componentName;
|
|
|
|
|
|
|
|
if (name) {
|
|
|
|
cb(child);
|
|
|
|
} else if (child.$children.length) {
|
|
|
|
child.$children.forEach((innerChild) => {
|
|
|
|
find(innerChild, cb);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (this.slideInstances.length) {
|
|
|
|
this.slideInstances.forEach((child) => {
|
|
|
|
find(child);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.$children.forEach((child) => {
|
|
|
|
find(child);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
updateSlides (init, slot = false) {
|
|
|
|
let slides = [];
|
|
|
|
let index = 1;
|
|
|
|
|
|
|
|
this.findChild((child) => {
|
|
|
|
slides.push({
|
|
|
|
$el: child.$el
|
|
|
|
});
|
|
|
|
child.index = index++;
|
|
|
|
|
|
|
|
if (init) {
|
|
|
|
this.slideInstances.push(child);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.slides = slides;
|
2017-01-16 18:02:51 -06:00
|
|
|
|
|
|
|
this.updatePos();
|
2017-01-16 04:00:52 -06:00
|
|
|
},
|
|
|
|
updatePos () {
|
|
|
|
this.findChild((child) => {
|
|
|
|
child.width = this.listWidth;
|
|
|
|
});
|
|
|
|
|
|
|
|
this.trackWidth = (this.slides.length || 0) * this.listWidth;
|
|
|
|
},
|
|
|
|
// use when slot changed
|
|
|
|
slotChange () {
|
2017-01-16 18:10:31 -06:00
|
|
|
this.$nextTick(() => {
|
|
|
|
this.slides = [];
|
|
|
|
this.slideInstances = [];
|
|
|
|
|
|
|
|
this.updateSlides(true, true);
|
|
|
|
this.updatePos();
|
|
|
|
});
|
2017-01-16 04:00:52 -06:00
|
|
|
},
|
|
|
|
handleResize () {
|
|
|
|
this.$nextTick(() => {
|
|
|
|
this.listWidth = parseInt(getStyle(this.$el, 'width'));
|
|
|
|
this.updatePos();
|
|
|
|
});
|
2017-01-16 04:12:46 -06:00
|
|
|
},
|
2017-01-16 17:43:20 -06:00
|
|
|
add (offset) {
|
|
|
|
let index = this.currentIndex;
|
|
|
|
index += offset;
|
2017-01-16 17:51:03 -06:00
|
|
|
while (index < 0) index += this.slides.length;
|
|
|
|
index = index % this.slides.length;
|
2017-01-17 14:29:51 -06:00
|
|
|
this.$emit('on-change', this.currentIndex, index);
|
2017-01-16 17:43:20 -06:00
|
|
|
this.currentIndex = index;
|
|
|
|
},
|
2017-01-17 14:29:51 -06:00
|
|
|
dotsEvent (event, n) {
|
2017-01-17 14:35:23 -06:00
|
|
|
if (event === this.trigger && this.currentIndex !== n) {
|
2017-01-17 14:29:51 -06:00
|
|
|
this.$emit('on-change', this.currentIndex, n);
|
|
|
|
this.currentIndex = n;
|
|
|
|
}
|
2017-01-16 04:28:34 -06:00
|
|
|
},
|
2017-01-16 04:12:46 -06:00
|
|
|
setAutoplay () {
|
2017-01-16 04:28:34 -06:00
|
|
|
window.clearInterval(this.timer);
|
2017-01-16 04:12:46 -06:00
|
|
|
if (this.autoplay) {
|
|
|
|
this.timer = window.setInterval(() => {
|
2017-01-16 17:43:20 -06:00
|
|
|
this.add(1);
|
2017-01-16 04:12:46 -06:00
|
|
|
}, this.autoplaySpeed);
|
|
|
|
}
|
2017-01-16 02:59:46 -06:00
|
|
|
}
|
2017-01-16 04:00:52 -06:00
|
|
|
},
|
|
|
|
compiled () {
|
|
|
|
this.updateSlides(true);
|
|
|
|
},
|
2017-01-16 04:12:46 -06:00
|
|
|
watch: {
|
|
|
|
autoplay () {
|
|
|
|
this.setAutoplay();
|
|
|
|
},
|
2017-01-16 04:28:34 -06:00
|
|
|
autoplaySpeed () {
|
|
|
|
this.setAutoplay();
|
|
|
|
},
|
2017-01-17 14:35:23 -06:00
|
|
|
currentIndex (val, oldVal) {
|
|
|
|
this.$emit('on-change', oldVal, val);
|
2017-01-16 04:28:34 -06:00
|
|
|
this.$nextTick(() => {
|
2017-01-17 14:29:51 -06:00
|
|
|
this.trackLeft = this.currentIndex * this.listWidth;
|
2017-01-16 04:28:34 -06:00
|
|
|
});
|
2017-01-16 04:12:46 -06:00
|
|
|
}
|
|
|
|
},
|
2017-01-16 04:00:52 -06:00
|
|
|
ready () {
|
|
|
|
this.handleResize();
|
2017-01-16 04:28:34 -06:00
|
|
|
this.setAutoplay();
|
2017-01-16 04:00:52 -06:00
|
|
|
window.addEventListener('resize', this.handleResize, false);
|
|
|
|
},
|
|
|
|
beforeDestroy () {
|
|
|
|
window.removeEventListener('resize', this.handleResize, false);
|
2017-01-16 02:59:46 -06:00
|
|
|
}
|
2017-01-16 02:45:11 -06:00
|
|
|
};
|
|
|
|
</script>
|