实现JavaScript通用进度条

JavaScript通用进度条

  这是一个结构简单、功能齐全的进度条

进度条效果图

进度条实例

进度条的基本功能

  • 进度条的宽度、高度、颜色等基本属性都可以自行调整,怎么好看怎么来
  • 监听点击事件和拖拽事件:事件监听会要求传入回调函数,你可以选择往回调函数中传入合适的参数,因此在回调函数中就可以控制其他元素

创建实例示范

let progress = new Progress({
    selector: '#progress',
    fill: 20,					// 初始内部进度为 20%
    click: function (scale){	// 进度条点击事件的回调函数
      console.log(scale);
    },
    drag: {
      dragging: function (scale){ // 进度条正在被拖拽的回调函数
        console.log(scale);
      },
      dragend: function (scale){ // 进度条拖拽完成时的回调函数
        console.log(scale);
      }
    }
  });

创建实例的配置项说明

  • 除了 selector 项必填,其他全部可选
  • 如果在创建实例时不填 click 项与 drag 项,初始化进度条将没有点击事件和拖拽事件
  • 当然,也可以后期在合适的地方再添加事件监听,调用实例 progress.progressClick([function])progress.progressDrag([function],[function]) 函数,可为进度条添加点击事件和拖拽事件监听
config = {
    selector: string,         // 进度条元素选择器 (必填)
    length: string | number,  // 进度条总长度
    fill: number,             // 初始进度,为百分数,值的区间是:0 - 100
    click: function,          // 监听进度条的点击事件,callback:传入:已经过长度变化后的比例
    drag: {                   // 监听进度条的拖拽事件
      dragging: function,     // 正在拖动进度条的回调函数, callback: 传入:拖动时进度的 时刻变化比例
      dragend: function       // 结束拖动进度条的回调函数, callback: 传入:拖动完成后进度的 最终比例
    }
  };

HTML结构

	<div id="progress">  <!-- 进度条整体 -->
    	<div class="progress-fill"></div>   <!-- 进度条内部可移动的部分 -->
 	</div>

CSS代码

	/* 进度条外层 */
    #progress{
      display: inline-block;
      width: 600px;  /* 进度条总长度 */
      height: 4px;
      background-color: rgba(255, 255, 255, 0.4);
      position: relative;
      top: 0;
      left: 0;
    }
    /* 进度条内部走动的部分 */
    .progress-fill{
      display: inline-block;
      width: 300px; /* 进度条已经过的长度 */
      height: 4px;
      background-color:rgba(255, 255, 255, 0.9);
      position: absolute;
      top: 0;
      left: 0;
    }
    /* 伪元素充当小圆点 */
    .progress-fill::after{ 
      content: "";
      display: inline-block;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      background-color:rgba(255, 255, 255, 0.9);
      position: absolute;
      top: -4px;
      right: -6px;
    }

进度条JS源码

  • 注意:此js文件依赖 jQuery ,此处使用的是 jQuery 1.11.0 版本
  • 可直接添加jQuery的cdn引用:<script src="https://cdn.bootcss.com/jquery/1.11.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
;(function($, win){
  
  /**
   * @description 进度条构造函数
   * @param {object} config  - 进度条配置项
   * @return {object} new Progress()
   * @example 
   *  let progress = new Progress({
   *    selector: '#progress',
   *    fill: 50,
   *    click: function (scale){},
   *    drag: {
   *      dragging: function (scale){},
   *      dragend: function (scale){}
   *    }
   *  });
   */
  function Progress(config) {
    return new Progress.prototype.init(config);
  }

  Progress.prototype = {
    constructor: Progress,

    /**
     * @description 初始化进度条
     * @param {object} config - 进度条配置项
     * @return {void}
     */
    init: function (config){
      this.$progress = $(config.selector).eq(0);
      this.progress = this.$progress.get(0);          // 进度条
      this.progressFill = this.progress.children[0];  // 走动的进度条
      this.$progressFill = $(this.progressFill);
      this.isDragging = false;                        // 标记进度条是否正在被拖动

      this._configure(config);                        // 对进度条进行配置
    },

     /**
     * @description 根据 config 配置项对进度条进行设置
     * @param {object} config - 配置项
     * @return {void}
     */
    _configure: function _configure(config){
      // config: selector,length,fill,click,drag
      let value = null;
      for (const key of Object.keys(config)) {
        value = config[key];
        switch (key.toLowerCase()) {
          case 'length':      this.progressWidth(value);                        break;
          case 'fill':        this.progressFillWidth(value);                    break;
          case 'click':       this.progressClick(value);                        break;
          case 'drag':        this.progressDrag(value.dragging, value.dragend); break;
          default:  break;
        }
      }
    },

    /**
     * @description 设置或者返回属性 isDragging ,进度条是否正在被拖动
     * @param {[boolean]} drag - true:表示进度条正在被拖拽,false:表示进度条没有被拖拽
     * @return {boolean} 当不传入参数时,返回属性 isDragging 
     */
    isDrag: function (drag){
      if(drag === undefined) {
        return this.isDragging;
      }
      this.isDragging = drag;
    },
    
    /**
     * @description 设置或者返回进度条总长度
     * @param {[string | number]} width - 新的长度值 ,如 "50px" 和 50 表示同样的长度
     * @return {number} 当不传入参数时,返回进度条的总长度
     */
    progressWidth: function (width){
      if(width === undefined) {
        return this.$progress.width();
      }
      width = parseFloat(width);
      if(typeof width !== 'number') {
        return;
      }
      let oldWidth = this.$progress.width();
      let fillWidth = parseFloat(width / oldWidth * this.progressFillWidth()); // 走动进度条在进度条总长度变化后的长度

      this.$progress.css('width',width+'px');  // 设置进度条总长度
      this.setProgressFillPixel(fillWidth);   // 设置走动进度条随比例变化 
      return width;
    },

    /**
     * @description 设置或者返回走动进度条的长度
     * @param {[string | number]} value - 走动进度条新的长度值,如字符 "150px" 表示指定像素长度, 数字 20 表示比例 20%
     * @return {number} 当不传入参数时,返回走动进度条的长度
     */
    progressFillWidth: function (value){
      if(value === undefined) {
        return this.$progressFill.width();
      }
      // 通过像素设置走动进度条的进度
      if(typeof value === 'string') {
        this.setProgressFillPixel(value);
      } 
      // 通过百分数设置走动进度条的进度
      else if(typeof value === 'number') {
        if(value > 100) {
          this.setProgressFillPixel(value); // 如果 value > 100,就不当做比例了,当做像素值
          return;
        }
        this.setProgressFillPercentage(value);
      }
    },

    /**
     * 通过像素设置走动进度条的进度
     * @param {number} width - 指定进度条已走过的长度
     * @return {number} 走动进度条变化后的长度值  
     */
     setProgressFillPixel: function(width){
      width = parseFloat(width);
      if(typeof width !== 'number') {
        return;
      }
      let proWidth = this.$progress.width(); // 进度条总长度
      width = width<0 ? 0 : (width>proWidth ? proWidth : width);
      this.$progressFill.css('width',width+'px');

      return width;
    },
    /**
     * 通过百分数设置走动进度条的进度
     * @param {number} percentage - 表示 已经过长度 与 进度条总长度 比例的百分数: 0 - 100
     * @return {number} 走动进度条变化后的长度值 
     */
    setProgressFillPercentage: function(percentage){
      percentage = parseFloat(percentage);
      if(typeof percentage !== 'number') {
        return;
      }
      percentage = percentage<0 ? 0 : (percentage>100 ? 100 : percentage);
      this.$progressFill.css('width',percentage+'%');

      return this.progressFillWidth();
    },

     /**
     * @description 监听进度条的点击事件
     * @param {function}  clickCallback - 点击进度条的回调函数,传入:点击后 已经过长度 与 进度条总长度 的比例
     * @return {void}
     */
    progressClick: function(clickCallback){
      let _this = this;
      let offsetLeft = 0; //进度条距离窗口左边的距离
      let clickX = 0;     //鼠标点击的横坐标位置
      let clickLength = 0;//进度条点击后的的长度
      let scale = 0;      //点击后的长度与进度条总长度的比例

      // 监听进度条的点击事件
      this.$progress.on('click',function(e){
        e = e || window.event;
        
        offsetLeft = $(this).offset().left; // 获取进度条距离窗口左边的距离
        clickX = e.pageX;                   // 获取鼠标点击的横坐标
        clickLength = clickX - offsetLeft;  // 进度条点击的长度

        // 设置走动进度条的长度
         _this. setProgressFillPixel(clickLength);
        
        // 计算点击长度与总长度的比例;注意 toFixed方法的返回值为 string 类型
        scale = clickLength / _this.progressWidth();
        scale = parseFloat(scale.toFixed(4));
        
        // 将比例返回给外界调用者
        if(typeof clickCallback === 'function') {
          clickCallback(scale);
        }
      });
    },

    /**
     * @description 监听进度条的拖动事件
     * @param {function} draggingCallback - 正在拖动进度条的回调函数,传入:拖动长度的 时刻变化比例
     * @param {function} dragEndCallback - 结束拖动进度条的回调函数, 传入:拖动长度的最终比例
     * @return {void}
     */
    progressDrag: function (draggingCallback, dragEndCallback){
      let _this = this;
      let progressWidth = 0; // 进度条总长度
      let offsetLeft = 0;    // 获取进度条距离窗口左边的距离
      let clickX = 0;        // 鼠标点击的位置
      let moveLength = 0;    // 拖拽的长度
      let scale = 0;         // 拖动的长度与进度条总长度的比例

      // 监听进度条的鼠标按下事件
      this.$progress.on('mousedown',function(){
        progressWidth = _this.progressWidth();
        offsetLeft = _this.$progress.offset().left;
        // 监听文档的鼠标移动事件
        $(document).on('mousemove',function(ev){
          ev = ev || window.event;
          clickX = ev.pageX;               // 获取鼠标点击的距离
          moveLength = clickX - offsetLeft;// 获取拖拽的长度

          // 是否超出进度条左边界 0 ,是否超出进度条右边界 progressWidth
          moveLength = moveLength<0 ? 0 : (moveLength>progressWidth ? progressWidth : moveLength);
          // 计算拖拽后的长度与总长度的比例,保留四位小数;
          scale = parseInt((moveLength / progressWidth)*10000) / 10000;

          // 将 拖动进度条时刻变化的比例 返回给外界调用者
          if(typeof draggingCallback === 'function'){
            draggingCallback(scale);
          }
          // 进度条是否正在被拖拽,正在拖拽
          _this.isDrag(true);
          // 更新进度
          _this.setProgressFillPixel(moveLength);
        });

        // 监听文档的鼠标抬起事件
        $(document).on('mouseup',function(){
          // document 一定要移除 mousemove事件 和 mouseup 事件
          $(document).off('mousemove');
          $(document).off('mouseup');

          // 进度条是否正在被拖拽,已结束拖拽
          _this.isDrag(false);
          // 将 拖动进度条的最终比例 返回给外界调用者
          if(typeof dragEndCallback === 'function'){
            dragEndCallback(scale);
          }
        });

        return false;
      });
    }

  };

  Progress.prototype.init.prototype = Progress.prototype;

  win.Progress = Progress;
  
}(window.jQuery,window));
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值