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 <template> 1 <template>
2 <div> 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 <Carousel-item> 4 <Carousel-item>
5 - <Card>  
6 - <div class="demo-carousel">1</div>  
7 - </Card> 5 + <div class="demo-carousel">1</div>
8 </Carousel-item> 6 </Carousel-item>
9 <Carousel-item> 7 <Carousel-item>
10 <div class="demo-carousel">2</div> 8 <div class="demo-carousel">2</div>
@@ -24,8 +22,8 @@ @@ -24,8 +22,8 @@
24 export default { 22 export default {
25 data () { 23 data () {
26 return { 24 return {
27 - v1: 1  
28 - } 25 + v1: 0
  26 + };
29 }, 27 },
30 methods: { 28 methods: {
31 push () { 29 push () {
src/components/carousel/carousel-item.vue
@@ -27,6 +27,15 @@ @@ -27,6 +27,15 @@
27 mounted () { 27 mounted () {
28 this.$parent.slotChange(); 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 beforeDestroy () { 39 beforeDestroy () {
31 this.$parent.slotChange(); 40 this.$parent.slotChange();
32 } 41 }
src/components/carousel/carousel.vue
@@ -4,9 +4,11 @@ @@ -4,9 +4,11 @@
4 <Icon type="chevron-left"></Icon> 4 <Icon type="chevron-left"></Icon>
5 </button> 5 </button>
6 <div :class="[prefixCls + '-list']"> 6 <div :class="[prefixCls + '-list']">
7 - <div :class="[prefixCls + '-track']" :style="trackStyles"> 7 + <div :class="[prefixCls + '-track', showCopyTrack ? '' : 'higher']" :style="trackStyles" ref="originTrack">
8 <slot></slot> 8 <slot></slot>
9 </div> 9 </div>
  10 + <div :class="[prefixCls + '-track', showCopyTrack ? 'higher' : '']" :style="copyTrackStyles" ref="copyTrack" v-if="loop">
  11 + </div>
10 </div> 12 </div>
11 <button :class="arrowClasses" class="right" @click="arrowEvent(1)"> 13 <button :class="arrowClasses" class="right" @click="arrowEvent(1)">
12 <Icon type="chevron-right"></Icon> 14 <Icon type="chevron-right"></Icon>
@@ -16,7 +18,7 @@ @@ -16,7 +18,7 @@
16 <li :class="[n - 1 === currentIndex ? prefixCls + '-active' : '']" 18 <li :class="[n - 1 === currentIndex ? prefixCls + '-active' : '']"
17 @click="dotsEvent('click', n - 1)" 19 @click="dotsEvent('click', n - 1)"
18 @mouseover="dotsEvent('hover', n - 1)"> 20 @mouseover="dotsEvent('hover', n - 1)">
19 - <button></button> 21 + <button :class="[radiusDot ? 'radius' : '']"></button>
20 </li> 22 </li>
21 </template> 23 </template>
22 </ul> 24 </ul>
@@ -48,6 +50,10 @@ @@ -48,6 +50,10 @@
48 type: Number, 50 type: Number,
49 default: 2000 51 default: 2000
50 }, 52 },
  53 + loop: {
  54 + type: Boolean,
  55 + default: false
  56 + },
51 easing: { 57 easing: {
52 type: String, 58 type: String,
53 default: 'ease' 59 default: 'ease'
@@ -59,6 +65,10 @@ @@ -59,6 +65,10 @@
59 return oneOf(value, ['inside', 'outside', 'none']); 65 return oneOf(value, ['inside', 'outside', 'none']);
60 } 66 }
61 }, 67 },
  68 + radiusDot: {
  69 + type: Boolean,
  70 + default: false
  71 + },
62 trigger: { 72 trigger: {
63 type: String, 73 type: String,
64 default: 'click', 74 default: 'click',
@@ -84,11 +94,16 @@ @@ -84,11 +94,16 @@
84 listWidth: 0, 94 listWidth: 0,
85 trackWidth: 0, 95 trackWidth: 0,
86 trackOffset: 0, 96 trackOffset: 0,
  97 + trackCopyOffset: 0,
  98 + showCopyTrack: false,
87 slides: [], 99 slides: [],
88 slideInstances: [], 100 slideInstances: [],
89 timer: null, 101 timer: null,
90 ready: false, 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 computed: { 109 computed: {
@@ -97,13 +112,27 @@ @@ -97,13 +112,27 @@
97 `${prefixCls}` 112 `${prefixCls}`
98 ]; 113 ];
99 }, 114 },
  115 + listStyle () {
  116 + return {
  117 + width: `${this.trackWidth * 2}px`,
  118 + };
  119 + },
100 trackStyles () { 120 trackStyles () {
101 return { 121 return {
102 width: `${this.trackWidth}px`, 122 width: `${this.trackWidth}px`,
103 - transform: `translate3d(-${this.trackOffset}px, 0px, 0px)`, 123 + transform: `translate3d(${-this.trackOffset}px, 0px, 0px)`,
104 transition: `transform 500ms ${this.easing}` 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 arrowClasses () { 136 arrowClasses () {
108 return [ 137 return [
109 `${prefixCls}-arrow`, 138 `${prefixCls}-arrow`,
@@ -142,6 +171,12 @@ @@ -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 updateSlides (init) { 180 updateSlides (init) {
146 let slides = []; 181 let slides = [];
147 let index = 1; 182 let index = 1;
@@ -158,7 +193,6 @@ @@ -158,7 +193,6 @@
158 }); 193 });
159 194
160 this.slides = slides; 195 this.slides = slides;
161 -  
162 this.updatePos(); 196 this.updatePos();
163 }, 197 },
164 updatePos () { 198 updatePos () {
@@ -185,21 +219,57 @@ @@ -185,21 +219,57 @@
185 this.updatePos(); 219 this.updatePos();
186 this.updateOffset(); 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 add (offset) { 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 index += offset; 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 arrowEvent (offset) { 265 arrowEvent (offset) {
197 this.setAutoplay(); 266 this.setAutoplay();
198 this.add(offset); 267 this.add(offset);
199 }, 268 },
200 dotsEvent (event, n) { 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 this.$emit('input', n); 273 this.$emit('input', n);
204 // Reset autoplay timer when trigger be activated 274 // Reset autoplay timer when trigger be activated
205 this.setAutoplay(); 275 this.setAutoplay();
@@ -215,7 +285,10 @@ @@ -215,7 +285,10 @@
215 }, 285 },
216 updateOffset () { 286 updateOffset () {
217 this.$nextTick(() => { 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,6 +301,11 @@
228 }, 301 },
229 currentIndex (val, oldVal) { 302 currentIndex (val, oldVal) {
230 this.$emit('on-change', oldVal, val); 303 this.$emit('on-change', oldVal, val);
  304 + },
  305 + trackIndex () {
  306 + this.updateOffset();
  307 + },
  308 + copyTrackIndex () {
231 this.updateOffset(); 309 this.updateOffset();
232 }, 310 },
233 height () { 311 height () {
src/styles/components/carousel.less
@@ -31,6 +31,9 @@ @@ -31,6 +31,9 @@
31 overflow: hidden; 31 overflow: hidden;
32 32
33 z-index: 1; 33 z-index: 1;
  34 + &.higher {
  35 + z-index: 2;
  36 + }
34 } 37 }
35 38
36 &-item { 39 &-item {
@@ -159,6 +162,11 @@ @@ -159,6 +162,11 @@
159 color: transparent; 162 color: transparent;
160 163
161 transition: all .5s; 164 transition: all .5s;
  165 + &.radius {
  166 + width: 6px;
  167 + height: 6px;
  168 + border-radius: 50%;
  169 + }
162 } 170 }
163 171
164 &:hover > button { 172 &:hover > button {
@@ -168,6 +176,9 @@ @@ -168,6 +176,9 @@
168 &.@{carousel-prefix-cls}-active > button { 176 &.@{carousel-prefix-cls}-active > button {
169 opacity: 1; 177 opacity: 1;
170 width: 24px; 178 width: 24px;
  179 + &.radius{
  180 + width: 6px;
  181 + }
171 } 182 }
172 } 183 }
173 } 184 }