美文网首页
vue进度条组件,可拖动调整进度(仿Slider)

vue进度条组件,可拖动调整进度(仿Slider)

作者: 羊驼626 | 来源:发表于2021-07-28 13:59 被阅读0次
<template>
  <div :class="$style['container']">
    <div
      ref="content"
      :class="$style['content-bg']"
      :style="{ height: `${height}px`, borderRadius: `${height / 2}px`, backgroundColor: backgroundColor }"
      @click="click"
    >
      <div
        :class="$style['content']"
        :style="{
          width: `${data}%`,
          height: `${height}px`,
          borderRadius: `${height / 2}px`,
          backgroundColor: color
        }"
      ></div>
      <div
        ref="point"
        :class="$style['point']"
        :style="{
          width: `${height * 3}px`,
          height: `${height * 3}px`,
          marginTop: `-${height * 2}px`,
          marginLeft: `${data}%`,
          backgroundColor: color
        }"
        @mousedown="mousedown"
      ></div>
    </div>
  </div>
</template>

<script>

export default {
  name: 'BaseProgress',
  model: {
    prop: 'data',
    event: 'change'
  },
  props: {
    data: {
      type: Number,
      required: true
    },
    height: {
      type: Number,
      required: false,
      default: 4
    },
    color: {
      type: String,
      required: false,
      default: '#fff'
    },
    backgroundColor: {
      type: String,
      required: false,
      default: '#aaa'
    }
  },
  data () {
    return {
    }
  },
  computed: {
    origin () {
      return this.getElementLeft(this.$refs.content)
    },
    width () {
      return this.$refs.content.offsetWidth
    }
  },
  mounted () {
    document.body.addEventListener('mouseup', this.mouseup)
  },
  methods: {
    getElementLeft (element) {
      var actualTop = element.offsetLeft // 这是获取元素距父元素顶部的距离
      var current = element.offsetParent // 这是获取父元素
      while (current !== null) {
        // 当它上面有元素时就继续执行
        actualTop += current.offsetLeft // 这是获取父元素距它的父元素顶部的距离累加起来
        current = current.offsetParent // 继续找父元素
      }
      return actualTop
    },
    click (e) {
      this.$emit(
        'change',
        Math.ceil(((e.clientX - this.origin) / this.width) * 100)
      )
    },
    mousedown (e) {
      document.body.addEventListener('mousemove', this.mousemove)
      this.$refs.point.style.visibility = 'visible'
      this.draging = true
    },
    mouseup (e) {
      if (!this.draging) {
        return
      }
      this.draging = false
      this.$refs.point.style.visibility = 'hidden'
      document.body.removeEventListener('mousemove', this.mousemove)
    },
    mousemove (e) {
      if (this.draging && e.clientX >= this.origin && e.clientX <= (this.origin + this.width)) {
        const diff = (e.clientX - this.origin) / this.width
        this.$emit('change', Math.ceil(diff * 100) >= 100 ? 100 : Math.ceil(diff * 100))
      }
    }
  }
}
</script>

<style lang="less" module>
.container {
  width: 100%;
  cursor: pointer;
  .content-bg {
    width: 100%;
    // background-color: #aaa;
    &:hover {
      .point {
        visibility: visible !important;
      }
    }
    .content {
      // background-color: #fff;
    }
    .point {
      transform: translateX(-50%);
      visibility: hidden;
      border-radius: 50%;
      // background-color: #fff;
    }
  }
}
</style>

相关文章