Commit e9989f2b8527ae389b943db2c88675c92d98a5b6
1 parent
373dfb3c
added horizontal dots
Showing
3 changed files
with
181 additions
and
39 deletions
Show diff stats
src/components/carousel/carousel.vue
1 | 1 | <template> |
2 | 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 | 6 | <div :class="[prefixCls + '-list']"> |
8 | 7 | <div :class="[prefixCls + '-track']" :style="trackStyles" v-el:slides> |
9 | 8 | <!-- opacity: 1; width: 4480px; transform: translate3d(-1120px, 0px, 0px); --> |
10 | 9 | <slot></slot> |
11 | 10 | </div> |
12 | 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 | 24 | </div> |
19 | 25 | </template> |
20 | 26 | <script> |
... | ... | @@ -26,9 +32,9 @@ |
26 | 32 | export default { |
27 | 33 | name: 'Carousel', |
28 | 34 | props: { |
29 | - arrows: { | |
30 | - type: Boolean, | |
31 | - default: false | |
35 | + arrow: { | |
36 | + type: String, | |
37 | + default: 'hover' | |
32 | 38 | }, |
33 | 39 | autoplay: { |
34 | 40 | type: Boolean, |
... | ... | @@ -43,8 +49,12 @@ |
43 | 49 | default: 'ease' |
44 | 50 | }, |
45 | 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 | 59 | vertical: { |
50 | 60 | type: Boolean, |
... | ... | @@ -66,7 +76,6 @@ |
66 | 76 | timer: null |
67 | 77 | } |
68 | 78 | }, |
69 | - // events: before-change(from, to), after-change(current, from) | |
70 | 79 | computed: { |
71 | 80 | classes () { |
72 | 81 | return [ |
... | ... | @@ -82,6 +91,23 @@ |
82 | 91 | transform: `translate3d(-${this.trackLeft}px, 0px, 0px)`, |
83 | 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 | 113 | methods: { |
... | ... | @@ -156,10 +182,14 @@ |
156 | 182 | index += offset; |
157 | 183 | while (index < 0) index += this.slides.length; |
158 | 184 | index = index % this.slides.length; |
185 | + this.$emit('on-change', this.currentIndex, index); | |
159 | 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 | 194 | setAutoplay () { |
165 | 195 | window.clearInterval(this.timer); |
... | ... | @@ -182,7 +212,7 @@ |
182 | 212 | }, |
183 | 213 | currentIndex () { |
184 | 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 | 41 | } |
42 | 42 | |
43 | 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 | 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 | 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 | 21 | </i-col> |
22 | 22 | <i-col span="4"> |
23 | 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 | 48 | </i-col> |
26 | 49 | </Row> |
27 | 50 | <Carousel style="width: 50%; border: solid 1px #000" |
28 | 51 | :current-index.sync="currentIndex" |
29 | 52 | :autoplay="autoplay" |
30 | 53 | :autoplay-speed="autoplaySpeed" |
54 | + :dots="dots" | |
55 | + :trigger="trigger" | |
56 | + :arrow="arrow" | |
31 | 57 | easing="linear"> |
32 | 58 | <Carousel-item v-if="!remove"> |
33 | 59 | <Alert type="warning" show-icon> |
... | ... | @@ -54,7 +80,10 @@ |
54 | 80 | autoplay: true, |
55 | 81 | autoplaySpeed: 2000, |
56 | 82 | remove: false, |
57 | - pushItem: [] | |
83 | + pushItem: [], | |
84 | + arrow: 'hover', | |
85 | + trigger: 'click', | |
86 | + dots: 'inside' | |
58 | 87 | } |
59 | 88 | }, |
60 | 89 | methods: { | ... | ... |