[new feature] Slider: add vertical prop (#3078)

This commit is contained in:
neverland 2019-04-02 09:18:42 +08:00 committed by GitHub
parent ee5e49bda0
commit 7e9ca167fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 151 additions and 11 deletions

View File

@ -53,6 +53,16 @@
</div> </div>
</van-slider> </van-slider>
</demo-block> </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> </demo-section>
</template> </template>
@ -66,7 +76,8 @@ export default {
title4: '指定步长', title4: '指定步长',
customStyle: '自定义样式', customStyle: '自定义样式',
customButton: '自定义按钮', customButton: '自定义按钮',
text: '当前值:' text: '当前值:',
vertical: '垂直方向'
}, },
'en-US': { 'en-US': {
title1: 'Basic Usage', title1: 'Basic Usage',
@ -75,7 +86,8 @@ export default {
title4: 'Step size', title4: 'Step size',
customStyle: 'Custom Style', customStyle: 'Custom Style',
customButton: 'Custom Button', customButton: 'Custom Button',
text: 'Current value: ' text: 'Current value: ',
vertical: 'Vertical'
} }
}, },
@ -86,7 +98,8 @@ export default {
value3: 50, value3: 50,
value4: 50, value4: 50,
value5: 50, value5: 50,
value6: 50 value6: 50,
value7: 50
}; };
}, },

View File

@ -74,6 +74,14 @@ export default {
</van-slider> </van-slider>
``` ```
#### Vertical
```html
<div :style="{ height: '100px' }">
<van-slider v-model="value" vertical />
</div>
```
### API ### API
| Attribute | Description | Type | Default | | Attribute | Description | Type | Default |
@ -86,6 +94,7 @@ export default {
| bar-height | Height of bar | `String` | `2px` | | bar-height | Height of bar | `String` | `2px` |
| active-color | Active color of bar | `String` | `#1989fa` | | active-color | Active color of bar | `String` | `#1989fa` |
| inactive-color | Inactive color of bar | `String` | `#e5e5e5` | | inactive-color | Inactive color of bar | `String` | `#e5e5e5` |
| vertical | Whether to display vertical | `Boolean` | `false` |
### Event ### Event

View File

@ -10,6 +10,7 @@ export default sfc({
min: Number, min: Number,
value: Number, value: Number,
disabled: Boolean, disabled: Boolean,
vertical: Boolean,
activeColor: String, activeColor: String,
inactiveColor: String, inactiveColor: String,
max: { max: {
@ -41,8 +42,12 @@ export default sfc({
if (this.disabled) return; if (this.disabled) return;
this.touchMove(event); this.touchMove(event);
const rect = this.$el.getBoundingClientRect(); 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); this.updateValue(this.startValue + diff);
}, },
@ -57,7 +62,10 @@ export default sfc({
if (this.disabled) return; if (this.disabled) return;
const rect = this.$el.getBoundingClientRect(); 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); this.updateValue(value, true);
}, },
@ -71,23 +79,33 @@ export default sfc({
}, },
format(value) { 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) { render(h) {
const { vertical } = this;
const style = { const style = {
background: this.inactiveColor background: this.inactiveColor
}; };
const mainAxis = vertical ? 'height' : 'width';
const crossAxis = vertical ? 'width' : 'height';
const barStyle = { const barStyle = {
width: `${this.format(this.value)}%`, [mainAxis]: `${this.format(this.value)}%`,
height: this.barHeight, [crossAxis]: this.barHeight,
background: this.activeColor background: this.activeColor
}; };
return ( 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('bar')} style={barStyle}>
<div <div
class={bem('button-wrapper')} class={bem('button-wrapper')}

View File

@ -39,4 +39,15 @@
&--disabled { &--disabled {
opacity: .3; opacity: .3;
} }
&--vertical {
height: 100%;
display: inline-block;
.van-slider__button-wrapper {
top: auto;
bottom: 0;
transform: translate3d(50%, 50%, 0);
}
}
} }

View File

@ -58,5 +58,16 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </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> </div>
`; `;

View File

@ -20,6 +20,16 @@ exports[`click bar 2`] = `
</div> </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`] = ` exports[`drag button 1`] = `
<div class="van-slider van-slider--disabled"> <div class="van-slider van-slider--disabled">
<div class="van-slider__bar" style="width: 50%; height: 2px;"> <div class="van-slider__bar" style="width: 50%; height: 2px;">
@ -39,3 +49,13 @@ exports[`drag button 2`] = `
</div> </div>
</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>
`;

View File

@ -1,11 +1,19 @@
import Slider from '..'; import Slider from '..';
import { mount, triggerDrag, trigger } from '../../../test/utils'; 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', () => { test('drag button', () => {
mockGetBoundingClientRect();
const wrapper = mount(Slider, { const wrapper = mount(Slider, {
attachToDocument: true,
propsData: { propsData: {
value: 50, value: 50,
disabled: true disabled: true
@ -26,6 +34,8 @@ test('drag button', () => {
}); });
it('click bar', () => { it('click bar', () => {
mockGetBoundingClientRect();
const wrapper = mount(Slider, { const wrapper = mount(Slider, {
propsData: { propsData: {
value: 50, value: 50,
@ -44,3 +54,40 @@ it('click bar', () => {
trigger(wrapper, 'click', 100, 0); trigger(wrapper, 'click', 100, 0);
expect(wrapper).toMatchSnapshot(); 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();
});

View File

@ -73,6 +73,16 @@ export default {
</van-slider> </van-slider>
``` ```
#### 垂直方向
Slider 垂直展示时,高度为 100% 父元素高度
```html
<div :style="{ height: '100px' }">
<van-slider v-model="value" vertical />
</div>
```
### API ### API
| 参数 | 说明 | 类型 | 默认值 | 版本 | | 参数 | 说明 | 类型 | 默认值 | 版本 |
@ -85,6 +95,7 @@ export default {
| bar-height | 进度条高度 | `String` | `2px` | 1.1.0 | | bar-height | 进度条高度 | `String` | `2px` | 1.1.0 |
| active-color | 进度条激活态颜色 | `String` | `#1989fa` | 1.5.1 | | active-color | 进度条激活态颜色 | `String` | `#1989fa` | 1.5.1 |
| inactive-color | 进度条默认颜色 | `String` | `#e5e5e5` | 1.5.1 | | inactive-color | 进度条默认颜色 | `String` | `#e5e5e5` | 1.5.1 |
| vertical | 是否垂直展示 | `Boolean` | `false` | 1.6.13 |
### Event ### Event