2016-07-27 06:15:02 +00:00
|
|
|
<template>
|
|
|
|
<div class="el-slider">
|
|
|
|
<el-input-number
|
2016-08-11 07:51:13 +00:00
|
|
|
v-model="inputValue"
|
2016-07-27 06:15:02 +00:00
|
|
|
v-if="showInput"
|
|
|
|
class="el-slider__input"
|
2016-10-21 06:56:14 +00:00
|
|
|
@keyup.native="onInputChange"
|
2016-08-11 07:51:13 +00:00
|
|
|
ref="input"
|
2016-07-27 06:15:02 +00:00
|
|
|
:step="step"
|
2016-10-22 12:12:57 +00:00
|
|
|
:disabled="disabled"
|
2016-07-27 06:15:02 +00:00
|
|
|
:min="min"
|
|
|
|
:max="max"
|
|
|
|
size="small">
|
|
|
|
</el-input-number>
|
|
|
|
<div class="el-slider__runway"
|
2016-10-22 12:12:57 +00:00
|
|
|
:class="{ 'show-input': showInput, 'disabled': disabled }"
|
2016-08-11 07:51:13 +00:00
|
|
|
@click="onSliderClick" ref="slider">
|
2016-07-27 06:15:02 +00:00
|
|
|
<div class="el-slider__bar" :style="{ width: currentPosition }"></div>
|
2016-10-19 06:53:32 +00:00
|
|
|
<div
|
|
|
|
class="el-slider__button-wrapper"
|
2016-10-22 12:12:57 +00:00
|
|
|
@mouseenter="handleMouseEnter"
|
|
|
|
@mouseleave="handleMouseLeave"
|
2016-10-19 06:53:32 +00:00
|
|
|
@mousedown="onButtonDown"
|
2016-10-22 12:12:57 +00:00
|
|
|
:class="{ 'hover': hovering, 'dragging': dragging }"
|
|
|
|
:style="{left: currentPosition}"
|
|
|
|
ref="button">
|
|
|
|
<el-tooltip placement="top" ref="tooltip">
|
|
|
|
<span slot="content">{{ value }}</span>
|
|
|
|
<div class="el-slider__button" :class="{ 'hover': hovering, 'dragging': dragging }"></div>
|
|
|
|
</el-tooltip>
|
2016-07-27 06:15:02 +00:00
|
|
|
</div>
|
|
|
|
<div class="el-slider__stop" v-for="item in stops" :style="{ 'left': item + '%' }" v-if="showStops"></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
2016-10-12 09:41:49 +00:00
|
|
|
<script type="text/babel">
|
2016-10-25 13:35:41 +00:00
|
|
|
import ElInputNumber from 'element-ui/packages/input-number';
|
|
|
|
import ElTooltip from 'element-ui/packages/tooltip';
|
2016-07-27 06:15:02 +00:00
|
|
|
import { getStyle } from 'wind-dom/src/style';
|
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'ElSlider',
|
|
|
|
|
|
|
|
props: {
|
|
|
|
min: {
|
|
|
|
type: Number,
|
|
|
|
default: 0
|
|
|
|
},
|
|
|
|
max: {
|
|
|
|
type: Number,
|
|
|
|
default: 100
|
|
|
|
},
|
|
|
|
step: {
|
|
|
|
type: Number,
|
|
|
|
default: 1
|
|
|
|
},
|
|
|
|
defaultValue: {
|
|
|
|
type: Number,
|
|
|
|
default: 0
|
|
|
|
},
|
|
|
|
value: {
|
|
|
|
type: Number,
|
|
|
|
default: 0
|
|
|
|
},
|
|
|
|
showInput: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
showStops: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
2016-10-22 12:12:57 +00:00
|
|
|
},
|
|
|
|
disabled: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
2016-07-27 06:15:02 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
components: {
|
2016-10-22 12:12:57 +00:00
|
|
|
ElInputNumber,
|
|
|
|
ElTooltip
|
2016-07-27 06:15:02 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
data() {
|
|
|
|
return {
|
2016-11-21 07:11:29 +00:00
|
|
|
precision: null,
|
2016-08-11 07:51:13 +00:00
|
|
|
inputValue: null,
|
|
|
|
timeout: null,
|
2016-07-27 06:15:02 +00:00
|
|
|
hovering: false,
|
|
|
|
dragging: false,
|
2016-10-19 06:53:32 +00:00
|
|
|
startX: 0,
|
|
|
|
currentX: 0,
|
|
|
|
startPos: 0,
|
2016-07-27 06:15:02 +00:00
|
|
|
newPos: null,
|
|
|
|
oldValue: this.value,
|
|
|
|
currentPosition: (this.value - this.min) / (this.max - this.min) * 100 + '%'
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
watch: {
|
2016-08-11 07:51:13 +00:00
|
|
|
inputValue(val) {
|
2016-09-09 06:27:49 +00:00
|
|
|
this.$emit('input', Number(val));
|
2016-08-11 07:51:13 +00:00
|
|
|
},
|
|
|
|
|
2016-07-27 06:15:02 +00:00
|
|
|
value(val) {
|
|
|
|
this.$nextTick(() => {
|
|
|
|
this.updatePopper();
|
|
|
|
});
|
2016-11-23 04:15:00 +00:00
|
|
|
if (typeof val !== 'number' || isNaN(val) || val < this.min) {
|
2016-08-11 07:51:13 +00:00
|
|
|
this.$emit('input', this.min);
|
2016-07-27 06:15:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (val > this.max) {
|
2016-08-11 07:51:13 +00:00
|
|
|
this.$emit('input', this.max);
|
2016-07-27 06:15:02 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-08-11 07:51:13 +00:00
|
|
|
this.inputValue = val;
|
2016-07-27 06:15:02 +00:00
|
|
|
this.setPosition((val - this.min) * 100 / (this.max - this.min));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
2016-10-22 12:12:57 +00:00
|
|
|
handleMouseEnter() {
|
|
|
|
this.hovering = true;
|
|
|
|
this.$refs.tooltip.showPopper = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
handleMouseLeave() {
|
|
|
|
this.hovering = false;
|
|
|
|
this.$refs.tooltip.showPopper = false;
|
2016-08-11 07:51:13 +00:00
|
|
|
},
|
|
|
|
|
2016-07-27 06:15:02 +00:00
|
|
|
updatePopper() {
|
2016-10-22 12:12:57 +00:00
|
|
|
this.$refs.tooltip.updatePopper();
|
2016-07-27 06:15:02 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
setPosition(newPos) {
|
2016-11-30 08:58:53 +00:00
|
|
|
if (newPos < 0) {
|
|
|
|
newPos = 0;
|
|
|
|
} else if (newPos > 100) {
|
|
|
|
newPos = 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
const lengthPerStep = 100 / ((this.max - this.min) / this.step);
|
|
|
|
const steps = Math.round(newPos / lengthPerStep);
|
|
|
|
let value = steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min;
|
|
|
|
if (this.precision) {
|
|
|
|
value = parseFloat(value.toFixed(this.precision));
|
|
|
|
}
|
|
|
|
this.$emit('input', value);
|
|
|
|
this.currentPosition = (this.value - this.min) / (this.max - this.min) * 100 + '%';
|
|
|
|
if (!this.dragging) {
|
|
|
|
if (this.value !== this.oldValue) {
|
|
|
|
this.$emit('change', this.value);
|
|
|
|
this.oldValue = this.value;
|
2016-07-27 06:15:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onSliderClick(event) {
|
2016-10-22 12:12:57 +00:00
|
|
|
if (this.disabled) return;
|
2016-11-21 07:11:29 +00:00
|
|
|
const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
|
|
|
|
this.setPosition((event.clientX - sliderOffsetLeft) / this.$sliderWidth * 100);
|
2016-07-27 06:15:02 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
onInputChange() {
|
|
|
|
if (this.value === '') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!isNaN(this.value)) {
|
|
|
|
this.setPosition((this.value - this.min) * 100 / (this.max - this.min));
|
|
|
|
}
|
2016-10-19 06:53:32 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
onDragStart(event) {
|
|
|
|
this.dragging = true;
|
|
|
|
this.startX = event.clientX;
|
|
|
|
this.startPos = parseInt(this.currentPosition, 10);
|
|
|
|
},
|
|
|
|
|
|
|
|
onDragging(event) {
|
|
|
|
if (this.dragging) {
|
2016-10-22 12:12:57 +00:00
|
|
|
this.$refs.tooltip.showPopper = true;
|
2016-10-19 06:53:32 +00:00
|
|
|
this.currentX = event.clientX;
|
2016-11-21 07:11:29 +00:00
|
|
|
const diff = (this.currentX - this.startX) / this.$sliderWidth * 100;
|
2016-10-19 06:53:32 +00:00
|
|
|
this.newPos = this.startPos + diff;
|
|
|
|
this.setPosition(this.newPos);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onDragEnd() {
|
|
|
|
if (this.dragging) {
|
|
|
|
this.dragging = false;
|
2016-10-22 12:12:57 +00:00
|
|
|
this.$refs.tooltip.showPopper = false;
|
2016-10-19 06:53:32 +00:00
|
|
|
this.setPosition(this.newPos);
|
|
|
|
window.removeEventListener('mousemove', this.onDragging);
|
|
|
|
window.removeEventListener('mouseup', this.onDragEnd);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onButtonDown(event) {
|
2016-10-22 12:12:57 +00:00
|
|
|
if (this.disabled) return;
|
2016-10-19 06:53:32 +00:00
|
|
|
this.onDragStart(event);
|
|
|
|
window.addEventListener('mousemove', this.onDragging);
|
|
|
|
window.addEventListener('mouseup', this.onDragEnd);
|
2016-07-27 06:15:02 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
$sliderWidth() {
|
2016-08-11 07:51:13 +00:00
|
|
|
return parseInt(getStyle(this.$refs.slider, 'width'), 10);
|
2016-07-27 06:15:02 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
stops() {
|
2016-11-21 07:11:29 +00:00
|
|
|
const stopCount = (this.max - this.value) / this.step;
|
|
|
|
const currentLeft = parseFloat(this.currentPosition);
|
|
|
|
const stepWidth = 100 * this.step / (this.max - this.min);
|
|
|
|
const result = [];
|
2016-07-27 06:15:02 +00:00
|
|
|
for (let i = 1; i < stopCount; i++) {
|
|
|
|
result.push(currentLeft + i * stepWidth);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
created() {
|
2016-11-23 04:15:00 +00:00
|
|
|
if (typeof this.value !== 'number' ||
|
|
|
|
isNaN(this.value) ||
|
|
|
|
this.value < this.min) {
|
2016-08-11 07:51:13 +00:00
|
|
|
this.$emit('input', this.min);
|
2016-10-19 06:53:32 +00:00
|
|
|
} else if (this.value > this.max) {
|
|
|
|
this.$emit('input', this.max);
|
2016-07-27 06:15:02 +00:00
|
|
|
}
|
2016-11-21 07:11:29 +00:00
|
|
|
if (this.step && this.step < 1) {
|
|
|
|
this.precision = this.step.toPrecision(1).split('.')[1].length;
|
|
|
|
}
|
2016-11-07 08:25:27 +00:00
|
|
|
this.inputValue = this.inputValue || this.value;
|
2016-07-27 06:15:02 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|