123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- <template>
- <div
- class="el-slider__button-wrapper"
- @mouseenter="handleMouseEnter"
- @mouseleave="handleMouseLeave"
- @mousedown="onButtonDown"
- @touchstart="onButtonDown"
- :class="{ hover: hovering, dragging: dragging }"
- :style="wrapperStyle"
- ref="button"
- tabindex="0"
- @focus="handleMouseEnter"
- @blur="handleMouseLeave"
- @keydown.left="onLeftKeyDown"
- @keydown.right="onRightKeyDown"
- @keydown.down.prevent="onLeftKeyDown"
- @keydown.up.prevent="onRightKeyDown">
- <el-tooltip
- placement="top"
- ref="tooltip"
- :popper-class="tooltipClass"
- :disabled="!showTooltip">
- <span slot="content">{{ formatValue }}</span>
- <div
- class="el-slider__button"
- :class="{ hover: hovering, dragging: dragging }"></div>
- </el-tooltip>
- </div>
- </template>
- <script>
- export default {
- name: 'ElSliderButton',
- components: {
-
- },
- props: {
- value: {
- type: Number,
- default: 0,
- },
- vertical: {
- type: Boolean,
- default: false,
- },
- tooltipClass: String,
- marks: Object,
- },
- data() {
- return {
- hovering: false,
- dragging: false,
- isClick: false,
- startX: 0,
- currentX: 0,
- startY: 0,
- currentY: 0,
- startPosition: 0,
- newPosition: null,
- oldValue: this.value,
- }
- },
- computed: {
- disabled() {
- return this.$parent.sliderDisabled
- },
- max() {
- return this.$parent.max
- },
- min() {
- return this.$parent.min
- },
- step() {
- return this.$parent.step
- },
- showTooltip() {
- return this.$parent.showTooltip
- },
- precision() {
- return this.$parent.precision
- },
- currentPosition() {
- if (this.marks) {
-
-
- const marks = Object.keys(this.marks).map(Number)
-
- const index = marks.findIndex(i => this.value < i)
- if (index === -1) return '100%'
-
-
- const value =
- (index - 1) / (marks.length - 1) +
- (this.value - marks[index - 1]) /
- (marks[index] - marks[index - 1]) /
- (marks.length - 1)
- return value > 1 ? '100%' : `${value * 100}%`
- } else {
-
- return `${((this.value - this.min) / (this.max - this.min)) * 100}%`
- }
- },
- enableFormat() {
- return this.$parent.formatTooltip instanceof Function
- },
- formatValue() {
- return (
- (this.enableFormat && this.$parent.formatTooltip(this.value)) ||
- this.value
- )
- },
- wrapperStyle() {
- return this.vertical
- ? { bottom: this.currentPosition }
- : { left: this.currentPosition }
- },
- },
- watch: {
- dragging(val) {
- this.$parent.dragging = val
- },
- },
- methods: {
- displayTooltip() {
- this.$refs.tooltip && (this.$refs.tooltip.showPopper = true)
- },
- hideTooltip() {
- this.$refs.tooltip && (this.$refs.tooltip.showPopper = false)
- },
- handleMouseEnter() {
- this.hovering = true
- this.displayTooltip()
- },
- handleMouseLeave() {
- this.hovering = false
- this.hideTooltip()
- },
- onButtonDown(event) {
- if (this.disabled) return
- event.preventDefault()
- this.onDragStart(event)
- window.addEventListener('mousemove', this.onDragging)
- window.addEventListener('touchmove', this.onDragging)
- window.addEventListener('mouseup', this.onDragEnd)
- window.addEventListener('touchend', this.onDragEnd)
- window.addEventListener('contextmenu', this.onDragEnd)
- },
- onLeftKeyDown() {
- if (this.disabled) return
- this.newPosition =
- parseFloat(this.currentPosition) -
- (this.step / (this.max - this.min)) * 100
- this.setPosition(this.newPosition)
- this.$parent.emitChange()
- },
- onRightKeyDown() {
- if (this.disabled) return
- this.newPosition =
- parseFloat(this.currentPosition) +
- (this.step / (this.max - this.min)) * 100
- this.setPosition(this.newPosition)
- this.$parent.emitChange()
- },
- onDragStart(event) {
- this.dragging = true
- this.isClick = true
- if (event.type === 'touchstart') {
- event.clientY = event.touches[0].clientY
- event.clientX = event.touches[0].clientX
- }
- if (this.vertical) {
- this.startY = event.clientY
- } else {
- this.startX = event.clientX
- }
- this.startPosition = parseFloat(this.currentPosition)
- this.newPosition = this.startPosition
- },
- onDragging(event) {
- if (this.dragging) {
- this.isClick = false
- this.displayTooltip()
- this.$parent.resetSize()
- let diff = 0
- if (event.type === 'touchmove') {
- event.clientY = event.touches[0].clientY
- event.clientX = event.touches[0].clientX
- }
- 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.setPosition(this.newPosition)
- }
- },
- onDragEnd() {
- if (this.dragging) {
-
- setTimeout(() => {
- this.dragging = false
- this.hideTooltip()
- if (!this.isClick) {
- this.setPosition(this.newPosition)
- this.$parent.emitChange()
- }
- }, 0)
- window.removeEventListener('mousemove', this.onDragging)
- window.removeEventListener('touchmove', this.onDragging)
- window.removeEventListener('mouseup', this.onDragEnd)
- window.removeEventListener('touchend', this.onDragEnd)
- window.removeEventListener('contextmenu', this.onDragEnd)
- }
- },
- setPosition(newPosition) {
- if (newPosition === null || isNaN(newPosition)) return
- if (newPosition < 0) {
- newPosition = 0
- } else if (newPosition > 100) {
- newPosition = 100
- }
- const lengthPerStep = 100 / ((this.max - this.min) / this.step)
- const steps = Math.round(newPosition / lengthPerStep)
- let value =
- steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min
- if (this.marks) {
-
-
- const marks = Object.keys(this.marks).map((current, index, arr) => {
- return {
- value: Number(current),
- perc: (100 * index) / (arr.length - 1),
- }
- })
-
- if (newPosition === 100) {
- value = marks[marks.length - 1].value
- } else {
- const index = marks.findIndex(item => item.perc > newPosition)
-
- if (index === -1) {
-
- value =
- marks[marks.length - 2].value +
- (marks.length - 1) *
- (((newPosition - marks[marks.length - 2].perc) / 100) *
- (marks[marks.length - 1].value -
- marks[marks.length - 2].value))
- } else {
- value =
- marks[index - 1].value +
- (marks.length - 1) *
- (((newPosition - marks[index - 1].perc) / 100) *
- (marks[index].value - marks[index - 1].value))
- }
- }
- }
- value = parseFloat(value.toFixed(this.precision))
- this.$emit('input', value)
- this.$nextTick(() => {
- this.displayTooltip()
- this.$refs.tooltip && this.$refs.tooltip.updatePopper()
- })
- if (!this.dragging && this.value !== this.oldValue) {
- this.oldValue = this.value
- }
- },
- },
- }
- </script>
|