iview/src/components/carousel/carousel.vue

205 lines
6.1 KiB
Vue
Raw Normal View History

2017-01-16 02:45:11 -06:00
<template>
2017-01-16 02:59:46 -06:00
<div :class="classes">
2017-01-16 17:43:20 -06:00
<div :class="[prefixCls + '-arrow', 'left']" @click="add(-1)">
2017-01-16 17:37:28 -06:00
<div class='placeholder'></div>
<Icon type="arrow-left-b"></Icon>
</div>
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-16 17:43:20 -06:00
<div :class="[prefixCls + '-arrow', 'right']" @click="add(1)">
2017-01-16 17:37:28 -06:00
<div class='placeholder'></div>
<Icon type="arrow-right-b"></Icon>
</div>
<!-- dots -->
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: {
arrows: {
type: Boolean,
default: false
},
autoplay: {
type: Boolean,
default: true
},
autoplaySpeed: {
type: Number,
default: 2000
},
easing: {
type: String,
default: 'ease'
},
dots: {
type: Boolean,
default: true
},
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
// events: before-change(from, to), after-change(current, from)
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
};
}
},
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;
},
updatePos () {
this.findChild((child) => {
child.width = this.listWidth;
});
this.trackWidth = (this.slides.length || 0) * this.listWidth;
},
// use when slot changed
slotChange () {
this.slides = [];
this.slideInstances = [];
},
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;
if (index === this.slides.length) index = 0;
this.currentIndex = index;
},
2017-01-16 04:28:34 -06:00
slide () {
this.trackLeft = this.currentIndex * this.listWidth;
},
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);
// watch slot changed
if (MutationObserver) {
this.observer = new MutationObserver(() => {
this.slotChange();
this.updateSlides(true, true);
});
this.observer.observe(this.$els.slides, {
childList: true,
characterData: true,
subtree: true
});
}
},
2017-01-16 04:12:46 -06:00
watch: {
autoplay () {
this.setAutoplay();
},
2017-01-16 04:28:34 -06:00
autoplaySpeed () {
this.setAutoplay();
},
currentIndex () {
this.$nextTick(() => {
this.slide();
});
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>