diff --git a/src/components/carousel/carousel-item.vue b/src/components/carousel/carousel-item.vue index b995e94..ea964c6 100644 --- a/src/components/carousel/carousel-item.vue +++ b/src/components/carousel/carousel-item.vue @@ -1,10 +1,26 @@ <template> - <div :class="prefixCls"><slot></slot></div> + <div :class="prefixCls" v-bind:style="styles">{{width}}<slot></slot></div> </template> <script> const prefixCls = 'ivu-carousel-item'; export default { - name: 'CarouselItem' + componentName: 'carousel-item', + + data () { + return { + prefixCls: prefixCls, + width: 0, + left: 0 + }; + }, + computed: { + styles () { + return { + width: `${this.width}px`, + left: `${this.left}px` + } + } + }, }; </script> diff --git a/src/components/carousel/carousel.vue b/src/components/carousel/carousel.vue index 680cd56..e048061 100644 --- a/src/components/carousel/carousel.vue +++ b/src/components/carousel/carousel.vue @@ -1,10 +1,18 @@ <template> <div :class="classes"> - <slot></slot> + <!-- button --> + <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> + <!-- button --> </div> </template> <script> import Icon from '../icon/icon.vue'; + import { oneOf, getStyle, deepCopy, getScrollBarSize } from '../../utils/assist'; const prefixCls = 'ivu-carousel'; @@ -40,6 +48,15 @@ default: false } }, + data () { + return { + prefixCls: prefixCls, + listWidth: 0, + trackWidth: 0, + slides: [], + slideInstances: [] + } + }, // events: before-change(from, to), after-change(current, from) computed: { classes () { @@ -49,7 +66,99 @@ [`${prefixCls}-vertical`]: this.vertical } ]; + }, + trackStyles () { + return { + width: `${this.trackWidth}px` + }; + } + }, + 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; + + // this.updateSlideWidth(); + }, + 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(); + }); } + }, + 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 + }); + } + }, + ready () { + this.handleResize(); + window.addEventListener('resize', this.handleResize, false); + }, + beforeDestroy () { + window.removeEventListener('resize', this.handleResize, false); } }; </script> diff --git a/src/styles/components/carousel.less b/src/styles/components/carousel.less index b440717..87557dc 100644 --- a/src/styles/components/carousel.less +++ b/src/styles/components/carousel.less @@ -8,4 +8,30 @@ user-select: none; touch-action: pan-y; -webkit-tap-highlight-color: transparent; + + &-track, &-list { + transform: translate3d(0, 0, 0); + } + + &-list { + position: relative; + display: block; + overflow: hidden; + + margin: 0; + padding: 0; + } + + &-track { + position: relative; + top: 0; + left: 0; + display: block; + } + + &-item { + float: left; + height: 100%; + min-height: 1px; + } } diff --git a/test/routers/carousel.vue b/test/routers/carousel.vue index 4dff775..ff9bab6 100644 --- a/test/routers/carousel.vue +++ b/test/routers/carousel.vue @@ -1,5 +1,5 @@ <template> - <Carousel> + <Carousel style="width: 400px"> <Carousel-item>test1</Carousel-item> <Carousel-item>test2</Carousel-item> <Carousel-item>test3</Carousel-item> -- libgit2 0.21.4