Commit ccf544dcc2499ddde06aa7bb0076d4885efc9055

Authored by houyl
1 parent 9b24f1ab

Merge branch 'master' of https://github.com/iview/iview into 2.0

Update carousel component: add loop and radiusDot property
# Conflicts:
#	package.json
#	src/components/date-picker/picker.vue
#	src/components/select/select.vue
examples/routers/carousel.vue
1 1 <template>
2 2 <div>
3   - <Carousel v-model="v1" dots="inside" trigger="hover">
  3 + <Carousel v-model="v1" dots="inside" trigger="hover" autoplay loop radius-dot>
4 4 <Carousel-item>
5   - <Card>
6   - <div class="demo-carousel">1</div>
7   - </Card>
  5 + <div class="demo-carousel">1</div>
8 6 </Carousel-item>
9 7 <Carousel-item>
10 8 <div class="demo-carousel">2</div>
... ... @@ -24,8 +22,8 @@
24 22 export default {
25 23 data () {
26 24 return {
27   - v1: 1
28   - }
  25 + v1: 0
  26 + };
29 27 },
30 28 methods: {
31 29 push () {
... ...
src/components/carousel/carousel-item.vue
... ... @@ -27,6 +27,15 @@
27 27 mounted () {
28 28 this.$parent.slotChange();
29 29 },
  30 + watch: {
  31 + width (val) {
  32 + if (val && this.$parent.loop) {
  33 + this.$nextTick(() => {
  34 + this.$parent.initCopyTrackDom();
  35 + });
  36 + }
  37 + }
  38 + },
30 39 beforeDestroy () {
31 40 this.$parent.slotChange();
32 41 }
... ...
src/components/carousel/carousel.vue
... ... @@ -4,9 +4,11 @@
4 4 <Icon type="chevron-left"></Icon>
5 5 </button>
6 6 <div :class="[prefixCls + '-list']">
7   - <div :class="[prefixCls + '-track']" :style="trackStyles">
  7 + <div :class="[prefixCls + '-track', showCopyTrack ? '' : 'higher']" :style="trackStyles" ref="originTrack">
8 8 <slot></slot>
9 9 </div>
  10 + <div :class="[prefixCls + '-track', showCopyTrack ? 'higher' : '']" :style="copyTrackStyles" ref="copyTrack" v-if="loop">
  11 + </div>
10 12 </div>
11 13 <button :class="arrowClasses" class="right" @click="arrowEvent(1)">
12 14 <Icon type="chevron-right"></Icon>
... ... @@ -16,7 +18,7 @@
16 18 <li :class="[n - 1 === currentIndex ? prefixCls + '-active' : '']"
17 19 @click="dotsEvent('click', n - 1)"
18 20 @mouseover="dotsEvent('hover', n - 1)">
19   - <button></button>
  21 + <button :class="[radiusDot ? 'radius' : '']"></button>
20 22 </li>
21 23 </template>
22 24 </ul>
... ... @@ -48,6 +50,10 @@
48 50 type: Number,
49 51 default: 2000
50 52 },
  53 + loop: {
  54 + type: Boolean,
  55 + default: false
  56 + },
51 57 easing: {
52 58 type: String,
53 59 default: 'ease'
... ... @@ -59,6 +65,10 @@
59 65 return oneOf(value, ['inside', 'outside', 'none']);
60 66 }
61 67 },
  68 + radiusDot: {
  69 + type: Boolean,
  70 + default: false
  71 + },
62 72 trigger: {
63 73 type: String,
64 74 default: 'click',
... ... @@ -84,11 +94,16 @@
84 94 listWidth: 0,
85 95 trackWidth: 0,
86 96 trackOffset: 0,
  97 + trackCopyOffset: 0,
  98 + showCopyTrack: false,
87 99 slides: [],
88 100 slideInstances: [],
89 101 timer: null,
90 102 ready: false,
91   - currentIndex: this.value
  103 + currentIndex: this.value,
  104 + trackIndex: this.value,
  105 + copyTrackIndex: this.value,
  106 + hideTrackPos: -1, // 默认左滑
92 107 };
93 108 },
94 109 computed: {
... ... @@ -97,13 +112,27 @@
97 112 `${prefixCls}`
98 113 ];
99 114 },
  115 + listStyle () {
  116 + return {
  117 + width: `${this.trackWidth * 2}px`,
  118 + };
  119 + },
100 120 trackStyles () {
101 121 return {
102 122 width: `${this.trackWidth}px`,
103   - transform: `translate3d(-${this.trackOffset}px, 0px, 0px)`,
  123 + transform: `translate3d(${-this.trackOffset}px, 0px, 0px)`,
104 124 transition: `transform 500ms ${this.easing}`
105 125 };
106 126 },
  127 + copyTrackStyles () {
  128 + return {
  129 + width: `${this.trackWidth}px`,
  130 + transform: `translate3d(${-this.trackCopyOffset}px, 0px, 0px)`,
  131 + transition: `transform 500ms ${this.easing}`,
  132 + position: 'absolute',
  133 + top: 0
  134 + };
  135 + },
107 136 arrowClasses () {
108 137 return [
109 138 `${prefixCls}-arrow`,
... ... @@ -142,6 +171,12 @@
142 171 });
143 172 }
144 173 },
  174 + // copy trackDom
  175 + initCopyTrackDom () {
  176 + this.$nextTick(() => {
  177 + this.$refs.copyTrack.innerHTML = this.$refs.originTrack.innerHTML;
  178 + });
  179 + },
145 180 updateSlides (init) {
146 181 let slides = [];
147 182 let index = 1;
... ... @@ -158,7 +193,6 @@
158 193 });
159 194  
160 195 this.slides = slides;
161   -
162 196 this.updatePos();
163 197 },
164 198 updatePos () {
... ... @@ -185,21 +219,57 @@
185 219 this.updatePos();
186 220 this.updateOffset();
187 221 },
  222 + updateTrackPos (index) {
  223 + if (this.showCopyTrack) {
  224 + this.trackIndex = index;
  225 + } else {
  226 + this.copyTrackIndex = index;
  227 + }
  228 + },
  229 + updateTrackIndex (index) {
  230 + if (this.showCopyTrack) {
  231 + this.copyTrackIndex = index;
  232 + } else {
  233 + this.trackIndex = index;
  234 + }
  235 + },
188 236 add (offset) {
189   - let index = this.currentIndex;
  237 + // 获取单个轨道的图片数
  238 + let slidesLen = this.slides.length;
  239 + // 如果是无缝滚动,需要初始化双轨道位置
  240 + if (this.loop) {
  241 + if (offset > 0) {
  242 + // 初始化左滑轨道位置
  243 + this.hideTrackPos = -1;
  244 + } else {
  245 + // 初始化右滑轨道位置
  246 + this.hideTrackPos = slidesLen;
  247 + }
  248 + this.updateTrackPos(this.hideTrackPos);
  249 + }
  250 + // 获取当前展示图片的索引值
  251 + let index = this.showCopyTrack ? this.copyTrackIndex : this.trackIndex;
190 252 index += offset;
191   - while (index < 0) index += this.slides.length;
192   - index = index % this.slides.length;
193   - this.currentIndex = index;
194   - this.$emit('input', index);
  253 + while (index < 0) index += slidesLen;
  254 + if (((offset > 0 && index === slidesLen) || offset < 0 && index === slidesLen - 1) && this.loop) {
  255 + // 极限值(左滑:当前索引为总图片张数, 右滑:当前索引为总图片张数 - 1)切换轨道
  256 + this.showCopyTrack = !this.showCopyTrack;
  257 + this.trackIndex += offset;
  258 + this.copyTrackIndex += offset;
  259 + } else {
  260 + if (!this.loop) index = index % this.slides.length;
  261 + this.updateTrackIndex(index);
  262 + }
  263 + this.$emit('input', index === this.slides.length ? 0 : index);
195 264 },
196 265 arrowEvent (offset) {
197 266 this.setAutoplay();
198 267 this.add(offset);
199 268 },
200 269 dotsEvent (event, n) {
201   - if (event === this.trigger && this.currentIndex !== n) {
202   - this.currentIndex = n;
  270 + let curIndex = this.showCopyTrack ? this.copyTrackIndex : this.trackIndex;
  271 + if (event === this.trigger && curIndex !== n) {
  272 + this.updateTrackIndex(n);
203 273 this.$emit('input', n);
204 274 // Reset autoplay timer when trigger be activated
205 275 this.setAutoplay();
... ... @@ -215,7 +285,10 @@
215 285 },
216 286 updateOffset () {
217 287 this.$nextTick(() => {
218   - this.trackOffset = this.currentIndex * this.listWidth;
  288 + /* hack: revise copyTrack offset (1px) */
  289 + let ofs = this.copyTrackIndex > 0 ? -1 : 1;
  290 + this.trackOffset = this.trackIndex * this.listWidth;
  291 + this.trackCopyOffset = this.copyTrackIndex * this.listWidth + ofs;
219 292 });
220 293 }
221 294 },
... ... @@ -228,6 +301,11 @@
228 301 },
229 302 currentIndex (val, oldVal) {
230 303 this.$emit('on-change', oldVal, val);
  304 + },
  305 + trackIndex () {
  306 + this.updateOffset();
  307 + },
  308 + copyTrackIndex () {
231 309 this.updateOffset();
232 310 },
233 311 height () {
... ...
src/styles/components/carousel.less
... ... @@ -31,6 +31,9 @@
31 31 overflow: hidden;
32 32  
33 33 z-index: 1;
  34 + &.higher {
  35 + z-index: 2;
  36 + }
34 37 }
35 38  
36 39 &-item {
... ... @@ -159,6 +162,11 @@
159 162 color: transparent;
160 163  
161 164 transition: all .5s;
  165 + &.radius {
  166 + width: 6px;
  167 + height: 6px;
  168 + border-radius: 50%;
  169 + }
162 170 }
163 171  
164 172 &:hover > button {
... ... @@ -168,6 +176,9 @@
168 176 &.@{carousel-prefix-cls}-active > button {
169 177 opacity: 1;
170 178 width: 24px;
  179 + &.radius{
  180 + width: 6px;
  181 + }
171 182 }
172 183 }
173 184 }
... ...