Slider: add vertical mode

pull/4375/head
devange 2017-04-11 13:44:54 +08:00 committed by 杨奕
parent 46650289b7
commit 8e1d8329aa
5 changed files with 189 additions and 17 deletions

View File

@ -10,7 +10,8 @@
value6: 0, value6: 0,
value7: 0, value7: 0,
value8: 0, value8: 0,
value9: [4, 8] value9: [4, 8],
value10: 0
}; };
}, },
methods: { methods: {
@ -171,6 +172,34 @@ Selecting a range of values is supported.
``` ```
::: :::
### Vertical mode
Vertical slider
:::demo Setting the `vertical` attribute to switch to the vertical mode, the `size` attribute must be setted as the heigth of slider
```html
<template>
<div class="block">
<el-slider
v-model="value10"
vertical
size="300px">
</el-slider>
</div>
</template>
<script>
export default {
data() {
return {
value10: 0
}
}
}
</script>
```
:::
## Attributes ## Attributes
| Attribute | Description | Type | Accepted Values | Default | | Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- | |---------- |-------------- |---------- |-------------------------------- |-------- |
@ -184,6 +213,8 @@ Selecting a range of values is supported.
| show-tooltip | whether to display tooltip value | boolean | — | true | | show-tooltip | whether to display tooltip value | boolean | — | true |
| format-tooltip | format to display tooltip value | Function(value) | — | — | | format-tooltip | format to display tooltip value | Function(value) | — | — |
| range | whether to select a range | boolean | — | false | | range | whether to select a range | boolean | — | false |
| vertical | vertical mode | boolean | — | false |
| size | width or height, it should be setted when vertical mode | String | — | - |
## Events ## Events
| Event Name | Description | Parameters | | Event Name | Description | Parameters |

View File

@ -10,7 +10,8 @@
value6: 0, value6: 0,
value7: 0, value7: 0,
value8: 0, value8: 0,
value9: [4, 8] value9: [4, 8],
value10: 0
}; };
}, },
methods: { methods: {
@ -195,6 +196,34 @@
``` ```
::: :::
### 竖向模式
竖向滑块
:::demo 设置`vertical`可使滑块变成竖向模式,必须设置滑块高度`size`属性
```html
<template>
<div class="block">
<el-slider
v-model="value10"
vertical
size="300px">
</el-slider>
</div>
</template>
<script>
export default {
data() {
return {
value10: 0
}
}
}
</script>
```
:::
### Attributes ### Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- | |---------- |-------------- |---------- |-------------------------------- |-------- |
@ -208,6 +237,8 @@
| show-tooltip | 是否显示 tooltip | boolean | — | true | | show-tooltip | 是否显示 tooltip | boolean | — | true |
| format-tooltip | 格式化 tooltip message | Function(value) | — | — | | format-tooltip | 格式化 tooltip message | Function(value) | — | — |
| range | 是否为范围选择 | boolean | — | false | | range | 是否为范围选择 | boolean | — | false |
| vertical | 是否竖向模式 | boolean | — | false |
| size | 宽度或高度,竖向模式时务必设置 | String | — | - |
### Events ### Events
| 事件名称 | 说明 | 回调参数 | | 事件名称 | 说明 | 回调参数 |

View File

@ -5,7 +5,7 @@
@mouseleave="handleMouseLeave" @mouseleave="handleMouseLeave"
@mousedown="onButtonDown" @mousedown="onButtonDown"
:class="{ 'hover': hovering, 'dragging': dragging }" :class="{ 'hover': hovering, 'dragging': dragging }"
:style="{ left: currentPosition }" :style="this.vertical ? { bottom: currentPosition } : { left: currentPosition }"
ref="button"> ref="button">
<el-tooltip placement="top" ref="tooltip" :disabled="!showTooltip"> <el-tooltip placement="top" ref="tooltip" :disabled="!showTooltip">
<span slot="content">{{ formatValue }}</span> <span slot="content">{{ formatValue }}</span>
@ -28,6 +28,10 @@
value: { value: {
type: Number, type: Number,
default: 0 default: 0
},
vertical: {
type: Boolean,
default: false
} }
}, },
@ -37,6 +41,8 @@
dragging: false, dragging: false,
startX: 0, startX: 0,
currentX: 0, currentX: 0,
startY: 0,
currentY: 0,
startPosition: 0, startPosition: 0,
newPosition: null, newPosition: null,
oldValue: this.value oldValue: this.value
@ -117,15 +123,25 @@
onDragStart(event) { onDragStart(event) {
this.dragging = true; this.dragging = true;
this.startX = event.clientX; if (this.vertical) {
this.startY = event.clientY;
} else {
this.startX = event.clientX;
}
this.startPosition = parseFloat(this.currentPosition); this.startPosition = parseFloat(this.currentPosition);
}, },
onDragging(event) { onDragging(event) {
if (this.dragging) { if (this.dragging) {
this.displayTooltip(); this.displayTooltip();
this.currentX = event.clientX; let diff = 0;
const diff = (this.currentX - this.startX) / this.$parent.$sliderWidth * 100; if (this.vertical) {
this.currentY = event.clientY;
diff = (this.startY - this.currentY) / this.$parent.$sliderSize * 100;
} else {
this.currentX = event.clientX;
diff = (this.currentX - this.startX) / this.$parent.$sliderSize * 100;
}
this.newPosition = this.startPosition + diff; this.newPosition = this.startPosition + diff;
this.setPosition(this.newPosition); this.setPosition(this.newPosition);
} }

View File

@ -1,5 +1,6 @@
<template> <template>
<div class="el-slider"> <div class="el-slider"
:class="{ 'el-slider__vertical': vertical, 'el-slider__with_input': showInput }">
<el-input-number <el-input-number
v-model="firstValue" v-model="firstValue"
v-if="showInput && !range" v-if="showInput && !range"
@ -14,20 +15,26 @@
</el-input-number> </el-input-number>
<div class="el-slider__runway" <div class="el-slider__runway"
:class="{ 'show-input': showInput, 'disabled': disabled }" :class="{ 'show-input': showInput, 'disabled': disabled }"
:style="vertical ? size && { height: size } : size && { width: size }"
@click="onSliderClick" @click="onSliderClick"
ref="slider"> ref="slider">
<div <div
class="el-slider__bar" class="el-slider__bar"
:style="{ :style="vertical ? {
width: barWidth, height: barSize,
left: barLeft bottom: barStart
} : {
width: barSize,
left: barStart
}"> }">
</div> </div>
<slider-button <slider-button
:vertical="vertical"
v-model="firstValue" v-model="firstValue"
ref="button1"> ref="button1">
</slider-button> </slider-button>
<slider-button <slider-button
:vertical="vertical"
v-model="secondValue" v-model="secondValue"
ref="button2" ref="button2"
v-if="range"> v-if="range">
@ -35,7 +42,7 @@
<div <div
class="el-slider__stop" class="el-slider__stop"
v-for="item in stops" v-for="item in stops"
:style="{ 'left': item + '%' }" :style="vertical ? { 'bottom': item + '%' } : { 'left': item + '%' }"
v-if="showStops"> v-if="showStops">
</div> </div>
</div> </div>
@ -94,6 +101,13 @@
range: { range: {
type: Boolean, type: Boolean,
default: false default: false
},
vertical: {
type: Boolean,
default: false
},
size: {
type: String
} }
}, },
@ -213,14 +227,19 @@
onSliderClick(event) { onSliderClick(event) {
if (this.disabled || this.dragging) return; if (this.disabled || this.dragging) return;
const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left; if (this.vertical) {
this.setPosition((event.clientX - sliderOffsetLeft) / this.$sliderWidth * 100); const sliderOffsetBottom = this.$refs.slider.getBoundingClientRect().bottom;
this.setPosition((event.clientY - sliderOffsetBottom) / this.$sliderSize * 100);
} else {
const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
this.setPosition((event.clientX - sliderOffsetLeft) / this.$sliderSize * 100);
}
} }
}, },
computed: { computed: {
$sliderWidth() { $sliderSize() {
return parseInt(getStyle(this.$refs.slider, 'width'), 10); return parseInt(getStyle(this.$refs.slider, (this.vertical ? 'height' : 'width')), 10);
}, },
stops() { stops() {
@ -248,13 +267,13 @@
return Math.max(this.firstValue, this.secondValue); return Math.max(this.firstValue, this.secondValue);
}, },
barWidth() { barSize() {
return this.range return this.range
? `${ 100 * (this.maxValue - this.minValue) / (this.max - this.min) }%` ? `${ 100 * (this.maxValue - this.minValue) / (this.max - this.min) }%`
: `${ 100 * (this.firstValue - this.min) / (this.max - this.min) }%`; : `${ 100 * (this.firstValue - this.min) / (this.max - this.min) }%`;
}, },
barLeft() { barStart() {
return this.range return this.range
? `${ 100 * (this.minValue - this.min) / (this.max - this.min) }%` ? `${ 100 * (this.minValue - this.min) / (this.max - this.min) }%`
: '0%'; : '0%';

View File

@ -128,5 +128,80 @@
background-color: var(--slider-stop-background-color); background-color: var(--slider-stop-background-color);
transform: translateX(-50%); transform: translateX(-50%);
} }
@e vertical {
position: relative;
.el-slider__runway {
width: 4px;
height: 100%;
margin: 0 16px;
}
.el-slider__bar {
width: 4px;
height: auto;
border-radius: 0 0 3px 3px;
}
.el-slider__button-wrapper {
top: auto;
left: var(--slider-button-wrapper-offset);
transform: translateY(50%);
}
.el-slider__stop {
transform: translateY(50%);
}
&.el-slider__with_input {
padding-bottom: var(--input-large-height);
.el-slider__input {
overflow: visible;
float: none;
position: absolute;
bottom: 0;
width: 36px;
margin-top: 15px;
.el-input__inner {
text-align: center;
padding-left: 5px;
padding-right: 5px;
}
.el-input-number__decrease,
.el-input-number__increase
{
top: var(--input-small-height);
margin-top: -1px;
border: var(--input-border);
line-height: 20px;
box-sizing: border-box;
transition: var(--border-transition-base);
}
.el-input-number__decrease {
width: 18px;
right: 18px;
border-bottom-left-radius: var(--input-border-radius);
}
.el-input-number__increase {
width: 19px;
border-bottom-right-radius: var(--input-border-radius);
& ~ .el-input .el-input__inner {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
&:hover {
.el-input-number__decrease,
.el-input-number__increase
{
border-color: var(--input-hover-border);
}
}
&:active {
.el-input-number__decrease,
.el-input-number__increase
{
border-color: var(--input-focus-border);
}
}
}
}
}
} }
} }