From 7e9ca167fad84afc9ba595763a41a21a9f643a7a Mon Sep 17 00:00:00 2001 From: neverland <chenjiahan@buaa.edu.cn> Date: Tue, 2 Apr 2019 09:18:42 +0800 Subject: [PATCH] [new feature] Slider: add vertical prop (#3078) --- packages/slider/demo/index.vue | 19 +++++-- packages/slider/en-US.md | 9 ++++ packages/slider/index.js | 30 ++++++++--- packages/slider/index.less | 11 ++++ .../test/__snapshots__/demo.spec.js.snap | 11 ++++ .../test/__snapshots__/index.spec.js.snap | 20 ++++++++ packages/slider/test/index.spec.js | 51 ++++++++++++++++++- packages/slider/zh-CN.md | 11 ++++ 8 files changed, 151 insertions(+), 11 deletions(-) diff --git a/packages/slider/demo/index.vue b/packages/slider/demo/index.vue index 2dd14769a..9354bb6e8 100644 --- a/packages/slider/demo/index.vue +++ b/packages/slider/demo/index.vue @@ -53,6 +53,16 @@ </div> </van-slider> </demo-block> + + <demo-block :title="$t('vertical')"> + <div :style="{ height: '120px', paddingLeft: '30px' }"> + <van-slider + v-model="value7" + vertical + @change="onChange" + /> + </div> + </demo-block> </demo-section> </template> @@ -66,7 +76,8 @@ export default { title4: '指定步长', customStyle: '自定义样式', customButton: '自定义按钮', - text: '当前值:' + text: '当前值:', + vertical: '垂直方向' }, 'en-US': { title1: 'Basic Usage', @@ -75,7 +86,8 @@ export default { title4: 'Step size', customStyle: 'Custom Style', customButton: 'Custom Button', - text: 'Current value: ' + text: 'Current value: ', + vertical: 'Vertical' } }, @@ -86,7 +98,8 @@ export default { value3: 50, value4: 50, value5: 50, - value6: 50 + value6: 50, + value7: 50 }; }, diff --git a/packages/slider/en-US.md b/packages/slider/en-US.md index f89337284..bdc71cb6f 100644 --- a/packages/slider/en-US.md +++ b/packages/slider/en-US.md @@ -74,6 +74,14 @@ export default { </van-slider> ``` +#### Vertical + +```html +<div :style="{ height: '100px' }"> + <van-slider v-model="value" vertical /> +</div> +``` + ### API | Attribute | Description | Type | Default | @@ -86,6 +94,7 @@ export default { | bar-height | Height of bar | `String` | `2px` | | active-color | Active color of bar | `String` | `#1989fa` | | inactive-color | Inactive color of bar | `String` | `#e5e5e5` | +| vertical | Whether to display vertical | `Boolean` | `false` | ### Event diff --git a/packages/slider/index.js b/packages/slider/index.js index 12ec5c19b..b2e83ecf3 100644 --- a/packages/slider/index.js +++ b/packages/slider/index.js @@ -10,6 +10,7 @@ export default sfc({ min: Number, value: Number, disabled: Boolean, + vertical: Boolean, activeColor: String, inactiveColor: String, max: { @@ -41,8 +42,12 @@ export default sfc({ if (this.disabled) return; this.touchMove(event); + const rect = this.$el.getBoundingClientRect(); - const diff = (this.deltaX / rect.width) * 100; + const delta = this.vertical ? this.deltaY : this.deltaX; + const total = this.vertical ? rect.height : rect.width; + const diff = (delta / total) * 100; + this.updateValue(this.startValue + diff); }, @@ -57,7 +62,10 @@ export default sfc({ if (this.disabled) return; const rect = this.$el.getBoundingClientRect(); - const value = ((event.clientX - rect.left) / rect.width) * 100; + const delta = this.vertical ? event.clientY - rect.top : event.clientX - rect.left; + const total = this.vertical ? rect.height : rect.width; + const value = (delta / total) * 100; + this.updateValue(value, true); }, @@ -71,23 +79,33 @@ export default sfc({ }, format(value) { - return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step; + return ( + Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step + ); } }, render(h) { + const { vertical } = this; const style = { background: this.inactiveColor }; + const mainAxis = vertical ? 'height' : 'width'; + const crossAxis = vertical ? 'width' : 'height'; + const barStyle = { - width: `${this.format(this.value)}%`, - height: this.barHeight, + [mainAxis]: `${this.format(this.value)}%`, + [crossAxis]: this.barHeight, background: this.activeColor }; return ( - <div style={style} class={bem({ disabled: this.disabled })} onClick={this.onClick}> + <div + style={style} + class={bem({ disabled: this.disabled, vertical })} + onClick={this.onClick} + > <div class={bem('bar')} style={barStyle}> <div class={bem('button-wrapper')} diff --git a/packages/slider/index.less b/packages/slider/index.less index c113d2510..c9ae76478 100644 --- a/packages/slider/index.less +++ b/packages/slider/index.less @@ -39,4 +39,15 @@ &--disabled { opacity: .3; } + + &--vertical { + height: 100%; + display: inline-block; + + .van-slider__button-wrapper { + top: auto; + bottom: 0; + transform: translate3d(50%, 50%, 0); + } + } } diff --git a/packages/slider/test/__snapshots__/demo.spec.js.snap b/packages/slider/test/__snapshots__/demo.spec.js.snap index 509249fc9..b59eebc3a 100644 --- a/packages/slider/test/__snapshots__/demo.spec.js.snap +++ b/packages/slider/test/__snapshots__/demo.spec.js.snap @@ -58,5 +58,16 @@ exports[`renders demo correctly 1`] = ` </div> </div> </div> + <div> + <div style="height:120px;padding-left:30px;"> + <div class="van-slider van-slider--vertical"> + <div class="van-slider__bar" style="height:50%;width:2px;"> + <div class="van-slider__button-wrapper"> + <div class="van-slider__button"></div> + </div> + </div> + </div> + </div> + </div> </div> `; diff --git a/packages/slider/test/__snapshots__/index.spec.js.snap b/packages/slider/test/__snapshots__/index.spec.js.snap index 02d26fc8d..9b1b41e6d 100644 --- a/packages/slider/test/__snapshots__/index.spec.js.snap +++ b/packages/slider/test/__snapshots__/index.spec.js.snap @@ -20,6 +20,16 @@ exports[`click bar 2`] = ` </div> `; +exports[`click vertical 1`] = ` +<div class="van-slider van-slider--vertical"> + <div class="van-slider__bar" style="height: 100%; width: 2px;"> + <div class="van-slider__button-wrapper"> + <div class="van-slider__button"></div> + </div> + </div> +</div> +`; + exports[`drag button 1`] = ` <div class="van-slider van-slider--disabled"> <div class="van-slider__bar" style="width: 50%; height: 2px;"> @@ -39,3 +49,13 @@ exports[`drag button 2`] = ` </div> </div> `; + +exports[`drag button vertical 1`] = ` +<div class="van-slider van-slider--vertical"> + <div class="van-slider__bar" style="height: 100%; width: 2px;"> + <div class="van-slider__button-wrapper"> + <div class="van-slider__button"></div> + </div> + </div> +</div> +`; diff --git a/packages/slider/test/index.spec.js b/packages/slider/test/index.spec.js index 682754841..85642d7ea 100644 --- a/packages/slider/test/index.spec.js +++ b/packages/slider/test/index.spec.js @@ -1,11 +1,19 @@ import Slider from '..'; import { mount, triggerDrag, trigger } from '../../../test/utils'; -Element.prototype.getBoundingClientRect = jest.fn(() => ({ width: 100, left: 0 })); +function mockGetBoundingClientRect(vertical) { + Element.prototype.getBoundingClientRect = jest.fn(() => ({ + width: vertical ? 0 : 100, + height: vertical ? 100 : 0, + top: vertical ? 0 : 100, + left: vertical ? 100 : 0 + })); +} test('drag button', () => { + mockGetBoundingClientRect(); + const wrapper = mount(Slider, { - attachToDocument: true, propsData: { value: 50, disabled: true @@ -26,6 +34,8 @@ test('drag button', () => { }); it('click bar', () => { + mockGetBoundingClientRect(); + const wrapper = mount(Slider, { propsData: { value: 50, @@ -44,3 +54,40 @@ it('click bar', () => { trigger(wrapper, 'click', 100, 0); expect(wrapper).toMatchSnapshot(); }); + +test('drag button vertical', () => { + mockGetBoundingClientRect(true); + + const wrapper = mount(Slider, { + propsData: { + value: 50, + vertical: true + } + }); + + wrapper.vm.$on('input', value => { + wrapper.setProps({ value }); + }); + + const button = wrapper.find('.van-slider__button'); + triggerDrag(button, 0, 50); + expect(wrapper).toMatchSnapshot(); +}); + +it('click vertical', () => { + mockGetBoundingClientRect(true); + + const wrapper = mount(Slider, { + propsData: { + value: 50, + vertical: true + } + }); + + wrapper.vm.$on('input', value => { + wrapper.setProps({ value }); + }); + + trigger(wrapper, 'click', 0, 100); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/packages/slider/zh-CN.md b/packages/slider/zh-CN.md index d430913ca..9d43b9262 100644 --- a/packages/slider/zh-CN.md +++ b/packages/slider/zh-CN.md @@ -73,6 +73,16 @@ export default { </van-slider> ``` +#### 垂直方向 + +Slider 垂直展示时,高度为 100% 父元素高度 + +```html +<div :style="{ height: '100px' }"> + <van-slider v-model="value" vertical /> +</div> +``` + ### API | 参数 | 说明 | 类型 | 默认值 | 版本 | @@ -85,6 +95,7 @@ export default { | bar-height | 进度条高度 | `String` | `2px` | 1.1.0 | | active-color | 进度条激活态颜色 | `String` | `#1989fa` | 1.5.1 | | inactive-color | 进度条默认颜色 | `String` | `#e5e5e5` | 1.5.1 | +| vertical | 是否垂直展示 | `Boolean` | `false` | 1.6.13 | ### Event