乐趣区

关于vue.js:vue可拖动水平进度条组件

须要一个可拖动并能设置最大最小值及步长的进度条,所以问了度娘,参考了很多网友写的进度条的代码,终于搞出了这个进度条组件,pc 端和挪动端均可用。

代码:

<template>
  <div class="progress-bar">
    <div class="num">{{num}}</div>
    <div class="mask">
      <div class="bar"><div class="point"></div></div>
    </div>
  </div>
</template>
<script>
export default {
  name: "progress-bar",
  props: {
    min: {
      // 最小值
      type: Number,
      default: 0
    },
    max: {
      // 最大值
      type: Number,
      default: 100
    },
    step: {
      // 每步的值为多少
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      num: this.value,
      test: ""
    };
  },
  mounted() {let dragSlide = () => {
      document.addEventListener(
        "touchmove",
        function(e) {e.preventDefault();
        },
        {passive: false}
      );
      // 勾销挪动端手势长按弹出提示框的操作
      document.addEventListener("contextmenu", function(e) {e.preventDefault();
      });
      this.point = document.querySelector(".point"); // 管制进度条的点
      this.pointWidth = parseInt(window.getComputedStyle(this.point, null).width
      );
      this.bar = document.querySelector(".bar"); // 进度条色彩层
      this.mask = document.querySelector(".mask"); // 进度条底层
      let lastX = null; // 判断鼠标挪动方向,解决向左侧滑动时候的 bug
      let move = e => {let x = e.touches[0].pageX;
        let direction = "";
        if (lastX == null) {
          lastX = x;
          return;
        }
        if (x > lastX) {direction = "right";} else if (x < lastX) {direction = "left";} else {direction = "";}
        let mask_left = this.getPosition(this.mask).left;
        let point_left = x - mask_left;
        if (point_left >= this.mask.offsetWidth - this.pointWidth) {
          // 控制点能够滑动的最大值就是进度条的宽度减去控制点的宽度;
          point_left = this.mask.offsetWidth - this.pointWidth;
        }
        if (point_left < 0) {
          // 控制点滑动的最小值不能为负
          point_left = 0;
        }
        this.point.style.left = point_left + "px";
        this.bar.style.width = point_left + this.pointWidth + "px";
        // 计算百分比
        let percent =
          (point_left / (this.mask.offsetWidth - this.pointWidth)) * 100;
        if (percent < 0.5 && direction == "right") {percent = Math.ceil(percent);
        } else if (percent > 0.5 && direction == "right") {percent = Math.floor(percent);
        } else {percent = Math.ceil(percent);
        }
        let value = (percent / 100) * (this.max - this.min) + this.min;
        let v = Math.floor(value / this.step);
        value = v * this.step;
        this.num = value;
      };
      this.point.addEventListener("touchmove", move);
    };
    let drag0 = new dragSlide();},
  methods: {getPosition(node) {
      // 获取元素的相对地位, 工具函数
      let left = node.offsetLeft; // 获取元素绝对于其父元素的 left 值 var left
      let top = node.offsetTop;
      let current = node.offsetParent; // 获得元素的 offsetParent // 始终循环直到根元素
      while (current != null) {
        left += current.offsetLeft;
        top += current.offsetTop;
        current = current.offsetParent;
      }
      return {
        left: left,
        top: top
      };
    }
  }
};
</script>
<style lang="scss">
* {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
.progress-bar {
  text-align: left;
  .mask {
    width: 320px;
    height: 20px;
    background-color: #dddddd;
    border-radius: 10px;
    position: absolute;
  }
  .bar {
    height: 20px;
    background-color: #1069db;
    position: absolute;
    z-index: 2;
    border-radius: 10px;
    bottom: 0;
    left: 0;
  }
  .point {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 1px solid #1069db;
    position: absolute;
    bottom: -3px;
    left: 0;
    z-index: 3;
    background-color: white;
  }
  .num {
    text-align: center;
    padding-bottom: 20px;
  }
}
</style>

组件应用办法:

// 例如:
<progress-bar :max="200000" :min="10000" :step="10000"/>
退出移动版