Commit e9989f2b8527ae389b943db2c88675c92d98a5b6

Authored by Rijn
1 parent 373dfb3c

added horizontal dots

src/components/carousel/carousel.vue
1 <template> 1 <template>
2 <div :class="classes"> 2 <div :class="classes">
3 - <div :class="[prefixCls + '-arrow', 'left']" @click="add(-1)">  
4 - <div class='placeholder'></div>  
5 - <Icon type="arrow-left-b"></Icon>  
6 - </div> 3 + <button :class="arrowClasses" class="left" @click="add(-1)">
  4 + <Icon type="chevron-left"></Icon>
  5 + </button>
7 <div :class="[prefixCls + '-list']"> 6 <div :class="[prefixCls + '-list']">
8 <div :class="[prefixCls + '-track']" :style="trackStyles" v-el:slides> 7 <div :class="[prefixCls + '-track']" :style="trackStyles" v-el:slides>
9 <!-- opacity: 1; width: 4480px; transform: translate3d(-1120px, 0px, 0px); --> 8 <!-- opacity: 1; width: 4480px; transform: translate3d(-1120px, 0px, 0px); -->
10 <slot></slot> 9 <slot></slot>
11 </div> 10 </div>
12 </div> 11 </div>
13 - <div :class="[prefixCls + '-arrow', 'right']" @click="add(1)">  
14 - <div class='placeholder'></div>  
15 - <Icon type="arrow-right-b"></Icon>  
16 - </div>  
17 - <!-- dots --> 12 + <button :class="arrowClasses" class="right" @click="add(1)">
  13 + <Icon type="chevron-right"></Icon>
  14 + </button>
  15 + <ul :class="dotsClasses">
  16 + <template v-for="n in slides.length">
  17 + <li :class="{ [`${prefixCls}-active`]: n === currentIndex }"
  18 + @click="dotsEvent('click', n)"
  19 + @mouseover="dotsEvent('hover', n)">
  20 + <button></button>
  21 + </li>
  22 + </template>
  23 + </ul>
18 </div> 24 </div>
19 </template> 25 </template>
20 <script> 26 <script>
@@ -26,9 +32,9 @@ @@ -26,9 +32,9 @@
26 export default { 32 export default {
27 name: 'Carousel', 33 name: 'Carousel',
28 props: { 34 props: {
29 - arrows: {  
30 - type: Boolean,  
31 - default: false 35 + arrow: {
  36 + type: String,
  37 + default: 'hover'
32 }, 38 },
33 autoplay: { 39 autoplay: {
34 type: Boolean, 40 type: Boolean,
@@ -43,8 +49,12 @@ @@ -43,8 +49,12 @@
43 default: 'ease' 49 default: 'ease'
44 }, 50 },
45 dots: { 51 dots: {
46 - type: Boolean,  
47 - default: true 52 + type: String,
  53 + default: 'inside'
  54 + },
  55 + trigger: {
  56 + type: String,
  57 + default: 'click'
48 }, 58 },
49 vertical: { 59 vertical: {
50 type: Boolean, 60 type: Boolean,
@@ -66,7 +76,6 @@ @@ -66,7 +76,6 @@
66 timer: null 76 timer: null
67 } 77 }
68 }, 78 },
69 - // events: before-change(from, to), after-change(current, from)  
70 computed: { 79 computed: {
71 classes () { 80 classes () {
72 return [ 81 return [
@@ -82,6 +91,23 @@ @@ -82,6 +91,23 @@
82 transform: `translate3d(-${this.trackLeft}px, 0px, 0px)`, 91 transform: `translate3d(-${this.trackLeft}px, 0px, 0px)`,
83 transition: `transform 500ms ${this.easing}` 92 transition: `transform 500ms ${this.easing}`
84 }; 93 };
  94 + },
  95 + arrowClasses () {
  96 + return [
  97 + `${prefixCls}-arrow`,
  98 + `${prefixCls}-arrow-${this.arrow}`
  99 + ]
  100 + },
  101 + dotsClasses () {
  102 + return [
  103 + `${prefixCls}-dots`,
  104 + `${prefixCls}-arrow-${this.dots}`
  105 + ]
  106 + },
  107 + activeDot (n) {
  108 + return {
  109 + [`${prefixCls}-vertical`]: this.currentIndex === n
  110 + }
85 } 111 }
86 }, 112 },
87 methods: { 113 methods: {
@@ -156,10 +182,14 @@ @@ -156,10 +182,14 @@
156 index += offset; 182 index += offset;
157 while (index < 0) index += this.slides.length; 183 while (index < 0) index += this.slides.length;
158 index = index % this.slides.length; 184 index = index % this.slides.length;
  185 + this.$emit('on-change', this.currentIndex, index);
159 this.currentIndex = index; 186 this.currentIndex = index;
160 }, 187 },
161 - slide () {  
162 - this.trackLeft = this.currentIndex * this.listWidth; 188 + dotsEvent (event, n) {
  189 + if (event === this.trigger) {
  190 + this.$emit('on-change', this.currentIndex, n);
  191 + this.currentIndex = n;
  192 + }
163 }, 193 },
164 setAutoplay () { 194 setAutoplay () {
165 window.clearInterval(this.timer); 195 window.clearInterval(this.timer);
@@ -182,7 +212,7 @@ @@ -182,7 +212,7 @@
182 }, 212 },
183 currentIndex () { 213 currentIndex () {
184 this.$nextTick(() => { 214 this.$nextTick(() => {
185 - this.slide(); 215 + this.trackLeft = this.currentIndex * this.listWidth;
186 }); 216 });
187 } 217 }
188 }, 218 },
src/styles/components/carousel.less
@@ -41,40 +41,123 @@ @@ -41,40 +41,123 @@
41 } 41 }
42 42
43 &-arrow { 43 &-arrow {
  44 +
  45 + border: none;
  46 + outline: none;
  47 +
  48 + padding: 0;
  49 + margin: 0;
  50 +
  51 + width: 36px;
  52 + height: 36px;
  53 + border-radius: 50%;
  54 +
  55 + cursor: pointer;
  56 +
  57 + display: none;
  58 +
44 position: absolute; 59 position: absolute;
45 - top: 0;  
46 - bottom: 0;  
47 - height: 100%; 60 + top: 50%;
  61 + z-index: 10;
  62 + transform: translateY(-50%);
  63 +
  64 + transition: .3s;
  65 + background-color: rgba(31, 45, 61, .11);
  66 + color: #fff;
  67 +
  68 + &:hover {
  69 + background-color: rgba(31, 45, 61, 0.5);
  70 + }
48 71
49 text-align: center; 72 text-align: center;
  73 + font-size: 1em;
  74 +
  75 + font-family: inherit;
  76 + line-height: inherit;
50 77
51 & > * { 78 & > * {
52 - display: inline-block;  
53 - vertical-align: middle; 79 + vertical-align: baseline;
54 } 80 }
55 81
56 - .placeholder{  
57 - overflow: hidden;  
58 - width: 0;  
59 - min-height: inherit;  
60 - height: inherit; 82 + &.left {
  83 + left: 16px;
61 } 84 }
62 85
63 - z-index: 3; 86 + &.right {
  87 + right: 16px;
  88 + }
64 89
65 - &.left {  
66 - left: 0; 90 + &-always {
  91 + display: inherit;
67 } 92 }
68 - &.right {  
69 - right: 0; 93 +
  94 + &-hover {
  95 + display: inherit;
  96 +
  97 + opacity: 0;
70 } 98 }
  99 + }
71 100
72 - width: 10%; 101 + &:hover &-arrow-hover {
  102 + opacity: 1;
  103 + }
73 104
74 - cursor: pointer; 105 + &-dots {
  106 + @padding: 7px;
75 107
76 - &:hover {  
77 - background: fade(#000, 30%); 108 + position: absolute;
  109 + bottom: 10px - @padding;
  110 +
  111 + list-style: none;
  112 + display: block;
  113 +
  114 + text-align: center;
  115 +
  116 + padding: 0;
  117 + width: 100%;
  118 + height: 3px + @padding * 2;
  119 +
  120 + li {
  121 + position: relative;
  122 + display: inline-block;
  123 +
  124 + vertical-align: top;
  125 + text-align: center;
  126 +
  127 + margin: 0 2px;
  128 + padding: @padding 0;
  129 +
  130 + cursor: pointer;
  131 +
  132 + button {
  133 + border: 0;
  134 + cursor: pointer;
  135 +
  136 + background: #8391a5;
  137 + opacity: 0.3;
  138 +
  139 + display: block;
  140 + width: 16px;
  141 + height: 3px;
  142 +
  143 + border-radius: 1px;
  144 + outline: none;
  145 +
  146 + font-size: 0;
  147 + color: transparent;
  148 +
  149 + -webkit-transition: all .5s;
  150 + transition: all .5s;
  151 + }
  152 +
  153 + &:hover > button {
  154 + opacity: 0.7;
  155 + }
  156 +
  157 + &.@{carousel-prefix-cls}-active > button {
  158 + opacity: 1;
  159 + width: 24px;
  160 + }
78 } 161 }
79 } 162 }
80 } 163 }
test/routers/carousel.vue
@@ -21,13 +21,39 @@ @@ -21,13 +21,39 @@
21 </i-col> 21 </i-col>
22 <i-col span="4"> 22 <i-col span="4">
23 <i-button @click="push">Push</i-button> 23 <i-button @click="push">Push</i-button>
24 - <i-button @click="remove = true">Remove</i-button> 24 + <i-button @click="remove = true">Remove Front</i-button>
  25 + </i-col>
  26 + <i-col span="4">
  27 + <p>Dots</p>
  28 + <Button-group>
  29 + <i-button @click="dots = 'inside'">Inside</i-button>
  30 + <i-button @click="dots = 'outside'">Outside</i-button>
  31 + <i-button @click="dots = 'none'">None</i-button>
  32 + </Button-group>
  33 + </i-col>
  34 + <i-col span="4">
  35 + <p>Trigger</p>
  36 + <Button-group>
  37 + <i-button @click="trigger = 'click'">Click</i-button>
  38 + <i-button @click="trigger = 'hover'">Hover</i-button>
  39 + </Button-group>
  40 + </i-col>
  41 + <i-col span="4">
  42 + Arrow
  43 + <Button-group>
  44 + <i-button @click="arrow = 'hover'">Hover</i-button>
  45 + <i-button @click="arrow = 'always'">Always</i-button>
  46 + <i-button @click="arrow = 'never'">Never</i-button>
  47 + </Button-group>
25 </i-col> 48 </i-col>
26 </Row> 49 </Row>
27 <Carousel style="width: 50%; border: solid 1px #000" 50 <Carousel style="width: 50%; border: solid 1px #000"
28 :current-index.sync="currentIndex" 51 :current-index.sync="currentIndex"
29 :autoplay="autoplay" 52 :autoplay="autoplay"
30 :autoplay-speed="autoplaySpeed" 53 :autoplay-speed="autoplaySpeed"
  54 + :dots="dots"
  55 + :trigger="trigger"
  56 + :arrow="arrow"
31 easing="linear"> 57 easing="linear">
32 <Carousel-item v-if="!remove"> 58 <Carousel-item v-if="!remove">
33 <Alert type="warning" show-icon> 59 <Alert type="warning" show-icon>
@@ -54,7 +80,10 @@ @@ -54,7 +80,10 @@
54 autoplay: true, 80 autoplay: true,
55 autoplaySpeed: 2000, 81 autoplaySpeed: 2000,
56 remove: false, 82 remove: false,
57 - pushItem: [] 83 + pushItem: [],
  84 + arrow: 'hover',
  85 + trigger: 'click',
  86 + dots: 'inside'
58 } 87 }
59 }, 88 },
60 methods: { 89 methods: {