美文网首页
JavaScript 原生实现进度条组件

JavaScript 原生实现进度条组件

作者: wdapp | 来源:发表于2020-02-02 00:57 被阅读0次
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>JavaScript 原生实现进度条组件</title>
      <style>
      * {
        margin: 0;
        padding: 0;
      }
    
      .container {
        width: 500px;
        height: 400px;
        position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -200px;
        margin-left: -250px;
        background-color: rgba(0, 0, 0, 0.5);
      }
    
      .container .slider {
        width: 100%;
        border-radius: 10px;
        height: 20px;
        border: 2px #eeeeee solid;
        background-color: white;
        position: absolute;
        bottom: 20px;
        box-sizing: border-box;
      }
    
      .container .slider .point {
        width: 20px;
        height: 20px;
        background-color: #6ac2f5;
        position: absolute;
        top: 50%;
        left: 0;
        margin-top: -10px;
        border-radius: 50%;
        border: 2px #000000 solid;
        box-sizing: border-box;
        pointer-events: none;
      }
    
      .container .slider .progress {
        width: 10px;
        height: 100%;
        background-color: #07c160;
        border-radius: 10px;
        pointer-events: none;
      }
      </style>
    </head>
    <body>
    
    <div class="container">
      <div class="slider" id="slider"></div>
    </div>
    
    <script>
    function Slider(options) {
      if (typeof options !== "object") {
        return false;
      }
      this.id = options.el || "slider";
      this.onchange = options.onchange;
      this.state = {
        isPress: false
      };
      this.init();
    }
    
    Slider.prototype.init = function() {
      this.el = document.querySelector(this.id);
      if (!this.el || this.el.nodeType !== 1) {
        return false;
      }
      this.point = this.createElement("point");
      this.progress = this.createElement("progress");
      this.el.append(this.progress, this.point);
    
      this.sliderWidth = this.el.clientWidth;
      this.pointWidth = this.point.clientWidth;
    
      this.addEvents(this.el);
    };
    
    Slider.prototype.createElement = function(tag) {
      var el = document.createElement("div");
      el.setAttribute("id", tag);
      el.setAttribute("class", tag);
      return el;
    };
    
    // 监听事件
    Slider.prototype.addEvents = function(target) {
      var _this = this;
      target.addEventListener("mousedown", this.mousedown.bind(_this), false);
      document.addEventListener("mousemove", this.mousemove.bind(_this), false);
      document.addEventListener("mouseup", this.mouseup.bind(_this), false);
    
      // 当窗口改变重新计算
      window.addEventListener("resize", this.debounce(function() {
        _this.sliderWidth = _this.el.clientWidth;
        _this.pointWidth = _this.point.clientWidth;
      }, 500));
    
      this.callThrottle = this.throttle(function(x) {
        _this.moveTo(x);
      }, 100);
      this.callDebounce = this.debounce(function(x) {
        _this.moveTo(x);
      }, 200);
    };
    
    Slider.prototype.mousedown = function(e) {
      this.callDebounce(e.offsetX);
      this.state.isPress = true;
    };
    
    Slider.prototype.mousemove = function(e) {
      if (this.state.isPress) {
        var offsetX = e.offsetX;
        var sliderWidth = this.sliderWidth;
        if (offsetX >= 0 && offsetX <= sliderWidth) {
          this.callThrottle(offsetX);
        }
      }
    };
    
    // 封装节流方法
    Slider.prototype.throttle = function(callback, interval) {
      var timestamp = Date.now();
      return function(e) {
        var currentTime = Date.now();
        if (currentTime - timestamp >= interval) {
          callback && callback(e);
          timestamp = Date.now();
        }
      };
    };
    
    // 封装防抖方法
    Slider.prototype.debounce = function(callback, delay) {
      var timer = 0;
      return function(e) {
        timer && clearTimeout(timer);
        timer = setTimeout(function() {
          callback && callback(e);
          timer = 0;
        }, delay);
      };
    };
    
    /*
    * 移动滑块和进度条
    * 计算移动限制
    * 返回onchange回调进度percent
    * */
    Slider.prototype.moveTo = function(x) {
      var sliderWidth = this.sliderWidth;
      var pointWidth = this.pointWidth;
      var half = pointWidth / 2;
      var percent = x / sliderWidth;
      if (x <= sliderWidth - pointWidth) {
        this.point.style.left = x + "px";
      } else {
        this.point.style.left = sliderWidth - pointWidth + "px";
        percent = 1;
      }
      if (x >= half && x <= sliderWidth - half) {
        this.progress.style.width = x + half + "px";
      } else if (x <= half) {
        this.progress.style.width = half + "px";
        percent = 0;
      } else if (x >= sliderWidth - half) {
        this.progress.style.width = sliderWidth - half + "px";
        percent = 1;
      }
      this.onchange && this.onchange(percent);
    };
    
    Slider.prototype.mouseup = function(e) {
      if (this.state.isPress) {
        this.state.isPress = false;
      }
    };
    
    // 初始化Slider插件
    var slider = new Slider({
      el: "#slider",
      // 进度变化回调函数
      onchange: function(e) {
        console.log("change", e);
      }
    });
    
    </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:JavaScript 原生实现进度条组件

          本文链接:https://www.haomeiwen.com/subject/vxyfxhtx.html