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 | <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: { |