element/packages/slider/src/main.vue

288 lines
7.4 KiB
Vue
Raw Normal View History

2016-07-27 06:15:02 +00:00
<template>
<div class="el-slider">
<el-input-number
v-model="firstValue"
2017-02-17 11:09:59 +00:00
v-if="showInput && !range"
2016-07-27 06:15:02 +00:00
class="el-slider__input"
2016-08-11 07:51:13 +00:00
ref="input"
2016-07-27 06:15:02 +00:00
:step="step"
:disabled="disabled"
:controls="showInputControls"
2016-07-27 06:15:02 +00:00
:min="min"
:max="max"
size="small">
</el-input-number>
<div class="el-slider__runway"
:class="{ 'show-input': showInput, 'disabled': disabled }"
2017-02-17 11:09:59 +00:00
@click="onSliderClick"
ref="slider">
2016-10-19 06:53:32 +00:00
<div
2017-02-17 11:09:59 +00:00
class="el-slider__bar"
:style="{
width: barWidth,
left: barLeft
}">
</div>
<slider-button
v-model="firstValue"
ref="button1">
</slider-button>
<slider-button
v-model="secondValue"
ref="button2"
v-if="range">
</slider-button>
<div
class="el-slider__stop"
v-for="item in stops"
:style="{ 'left': item + '%' }"
v-if="showStops">
2016-07-27 06:15:02 +00:00
</div>
</div>
</div>
</template>
<script type="text/babel">
2016-10-25 13:35:41 +00:00
import ElInputNumber from 'element-ui/packages/input-number';
2017-02-17 11:09:59 +00:00
import SliderButton from './button.vue';
2016-12-26 03:41:15 +00:00
import { getStyle } from 'element-ui/src/utils/dom';
2016-07-27 06:15:02 +00:00
export default {
name: 'ElSlider',
props: {
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
value: {
2017-02-17 11:09:59 +00:00
type: [Number, Array],
2016-07-27 06:15:02 +00:00
default: 0
},
showInput: {
type: Boolean,
default: false
},
showInputControls: {
type: Boolean,
default: true
},
2016-07-27 06:15:02 +00:00
showStops: {
type: Boolean,
default: false
},
2017-03-10 14:24:04 +00:00
showTooltip: {
type: Boolean,
default: true
},
formatTooltip: Function,
disabled: {
type: Boolean,
default: false
2017-02-17 11:09:59 +00:00
},
range: {
type: Boolean,
default: false
2016-07-27 06:15:02 +00:00
}
},
components: {
ElInputNumber,
2017-02-17 11:09:59 +00:00
SliderButton
2016-07-27 06:15:02 +00:00
},
data() {
return {
2017-02-17 11:09:59 +00:00
firstValue: null,
secondValue: null,
oldValue: null,
dragging: false
2016-07-27 06:15:02 +00:00
};
},
watch: {
2017-02-17 11:09:59 +00:00
value(val, oldVal) {
if (this.dragging ||
Array.isArray(val) &&
Array.isArray(oldVal) &&
val.every((item, index) => item === oldVal[index])) {
2016-07-27 06:15:02 +00:00
return;
}
2017-02-17 11:09:59 +00:00
this.setValues();
2016-08-11 07:51:13 +00:00
},
2017-02-17 11:09:59 +00:00
dragging(val) {
if (!val) {
this.setValues();
}
2016-07-27 06:15:02 +00:00
},
2017-02-17 11:09:59 +00:00
firstValue(val) {
if (this.range) {
this.$emit('input', [this.minValue, this.maxValue]);
} else {
this.$emit('input', val);
2016-11-30 08:58:53 +00:00
}
2017-02-17 11:09:59 +00:00
},
2016-11-30 08:58:53 +00:00
2017-02-17 11:09:59 +00:00
secondValue() {
if (this.range) {
this.$emit('input', [this.minValue, this.maxValue]);
2016-07-27 06:15:02 +00:00
}
},
2017-02-17 11:09:59 +00:00
min() {
this.setValues();
2016-07-27 06:15:02 +00:00
},
2017-02-17 11:09:59 +00:00
max() {
this.setValues();
}
},
2016-10-19 06:53:32 +00:00
2017-02-17 11:09:59 +00:00
methods: {
valueChanged() {
if (this.range) {
return ![this.minValue, this.maxValue]
.every((item, index) => item === this.oldValue[index]);
} else {
return this.value !== this.oldValue;
}
2016-10-19 06:53:32 +00:00
},
2017-02-17 11:09:59 +00:00
setValues() {
const val = this.value;
if (this.range && Array.isArray(val)) {
if (val[1] < this.min) {
this.$emit('input', [this.min, this.min]);
} else if (val[0] > this.max) {
this.$emit('input', [this.max, this.max]);
} else if (val[0] < this.min) {
this.$emit('input', [this.min, val[1]]);
} else if (val[1] > this.max) {
this.$emit('input', [val[0], this.max]);
} else {
this.firstValue = val[0];
this.secondValue = val[1];
if (this.valueChanged()) {
this.$emit('change', [this.minValue, this.maxValue]);
this.oldValue = val.slice();
}
}
} else if (!this.range && typeof val === 'number' && !isNaN(val)) {
if (val < this.min) {
this.$emit('input', this.min);
} else if (val > this.max) {
this.$emit('input', this.max);
} else {
this.firstValue = val;
if (this.valueChanged()) {
this.$emit('change', val);
this.oldValue = val;
}
}
2016-10-19 06:53:32 +00:00
}
},
2017-02-17 11:09:59 +00:00
setPosition(percent) {
const targetValue = this.min + percent * (this.max - this.min) / 100;
if (!this.range) {
this.$refs.button1.setPosition(percent);
return;
2016-10-19 06:53:32 +00:00
}
2017-02-17 11:09:59 +00:00
let button;
if (Math.abs(this.minValue - targetValue) < Math.abs(this.maxValue - targetValue)) {
button = this.firstValue < this.secondValue ? 'button1' : 'button2';
} else {
button = this.firstValue > this.secondValue ? 'button1' : 'button2';
}
this.$refs[button].setPosition(percent);
2016-10-19 06:53:32 +00:00
},
2017-02-17 11:09:59 +00:00
onSliderClick(event) {
if (this.disabled || this.dragging) return;
const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
this.setPosition((event.clientX - sliderOffsetLeft) / this.$sliderWidth * 100);
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() {
2017-02-17 11:09:59 +00:00
const stopCount = (this.max - this.min) / this.step;
2016-11-21 07:11:29 +00:00
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++) {
2017-02-17 11:09:59 +00:00
result.push(i * stepWidth);
2016-07-27 06:15:02 +00:00
}
2017-02-17 11:09:59 +00:00
if (this.range) {
return result.filter(step => {
return step < 100 * (this.minValue - this.min) / (this.max - this.min) ||
step > 100 * (this.maxValue - this.min) / (this.max - this.min);
});
} else {
return result.filter(step => step > 100 * (this.firstValue - this.min) / (this.max - this.min));
}
},
minValue() {
return Math.min(this.firstValue, this.secondValue);
},
maxValue() {
return Math.max(this.firstValue, this.secondValue);
},
barWidth() {
return this.range
? `${ 100 * (this.maxValue - this.minValue) / (this.max - this.min) }%`
: `${ 100 * (this.firstValue - this.min) / (this.max - this.min) }%`;
},
barLeft() {
return this.range
? `${ 100 * (this.minValue - this.min) / (this.max - this.min) }%`
: '0%';
},
precision() {
let precisions = [this.min, this.max, this.step].map(item => {
let decimal = ('' + item).split('.')[1];
return decimal ? decimal.length : 0;
});
return Math.max.apply(null, precisions);
2016-07-27 06:15:02 +00:00
}
},
2017-02-17 11:09:59 +00:00
mounted() {
if (this.range) {
if (Array.isArray(this.value)) {
this.firstValue = Math.max(this.min, this.value[0]);
this.secondValue = Math.min(this.max, this.value[1]);
} else {
this.firstValue = this.min;
this.secondValue = this.max;
}
this.oldValue = [this.firstValue, this.secondValue];
} else {
if (typeof this.value !== 'number' || isNaN(this.value)) {
this.firstValue = this.min;
} else {
this.firstValue = Math.min(this.max, Math.max(this.min, this.value));
}
this.oldValue = this.firstValue;
2016-07-27 06:15:02 +00:00
}
}
};
</script>