私人tool.js

個(gè)人總結(jié)的一些js工具代碼

/* eslint-disable */
// 如果是在vue項(xiàng)目中引入的話,上面的注釋用來避免vue中的eslint語法檢查
// 使用方法盈简,在html中通過script標(biāo)簽引入, <script src="./js/myTool.js"></script>维蒙,不管是vue項(xiàng)目還是普通項(xiàng)目贡这,可全局使用
// 在vue的main.js文件中通過import './assets/js/myTool' 的方式引入,全局使用
// 在vue組件中使用的話轻黑,import '../../assets/js/myTool',只能在當(dāng)前組件中使用

(function(){
  // ******判斷一個(gè)變量是否是dom元素******
  // 首先要對(duì)HTMLElement進(jìn)行類型檢查,因?yàn)榧词乖谥С諬TMLElement
  // 的瀏覽器中移迫,類型卻是有差別的,在Chrome,Opera中HTMLElement的
  // 類型為function管行,此時(shí)就不能用它來判斷了
  const isDOM = ( typeof HTMLElement === 'object' ) ?
      function(obj){
          return obj instanceof HTMLElement;
      } : 
      function(obj){
          return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
      }


  // ******獲取整數(shù)隨機(jī)數(shù)******
  function getRandomInt(min, max) {
      min = Math.ceil(min);
      max = Math.floor(max);
      return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive 
    }


  // ******時(shí)間格式化函數(shù)******
  function dateFmt(fmt, dateVal) {
      if (typeof(fmt) != 'string') return '格式化參數(shù)有誤厨埋!';       
      // 如果剛開始傳入的時(shí)間參數(shù)是一個(gè)小于30*24*3600*1000毫秒數(shù)的數(shù)字,那么應(yīng)該是求一個(gè)時(shí)間差值(否則就是求日期格式化)捐顷,求時(shí)間差需要對(duì)東八區(qū)的小時(shí)數(shù)進(jìn)行額外處理,因?yàn)閚ew Date(毫秒數(shù))是帶著時(shí)區(qū)值的荡陷,并且北京時(shí)間要比格林威治時(shí)間快8個(gè)小時(shí),所以格式化后小時(shí)上會(huì)多出8小時(shí),應(yīng)減去迅涮。
      // 當(dāng)然生成的該對(duì)象不僅可能是時(shí)間废赞,也可能是格林尼治一月份日期(參數(shù)中加上年月日就可以了)。
      if((typeof(dateVal) === 'number') && dateVal < 30 * 24 * 3600 * 1000 && !fmt.includes('M')) {//該條件用于判定是否是求時(shí)間差
          dateVal = new Date(dateVal - 8 * 3600 * 1000);
      }

      return fmtDate(fmt, dateVal);
      
      // 用于格式化日期(或時(shí)間差)的方法
      function fmtDate(fmt, dateVal) {
          // 校驗(yàn)參數(shù)并對(duì)象化日期參數(shù)(轉(zhuǎn)成日期對(duì)象)
          let date;
          if(dateVal || dateVal === 0) {
              date = new Date(dateVal);                
          }else {
              date = new Date();
          }
          if (date.toString() == 'Invalid Date') return '時(shí)間參數(shù)有誤';

          // 單獨(dú)處理年數(shù)
          let year = date.getFullYear() + '';
          let reg = /y+/g;
          let mYear = fmt.match(reg);
          if(mYear) {
              let mYearStr = mYear[0];
              year = year.substr(4 - mYearStr.length);
              fmt = fmt.replace(mYearStr, year);
          }
          
          // 獲取其余時(shí)間值
          let dates = {
              'M' : date.getMonth() + 1,
              'd' : date.getDate(),
              'h' : date.getHours(),
              'm' : date.getMinutes(),
              's' : date.getSeconds()
          }

          // 處理替換剩余時(shí)間值叮姑,并返回結(jié)果
          let regs = /[Mdhms]+/g;
          let rst = fmt.replace(regs, function (mth) {
              let item = mth[0];
              let value = dates[item];
              if(!value && value != 0) return ""; 
              if(mth.length == 1) {
                  return dates[mth];
              }else {
                  return ('00' + value).substr(String(value).length);
              }

          })
          let result = {
              year: year,
              month: dates.M,
              day: dates.d,
              hour: dates.h,
              minute: dates.m,
              second: dates.s
          }
          result.fmtTimeStr = rst;
          return result;
      }
              
  }


  // ******函數(shù)防抖******
  /**
   解釋:函數(shù)防抖是優(yōu)化高頻率執(zhí)行js代碼的一種手段蛹头,可以讓被調(diào)用的函數(shù)在一
   次連續(xù)的高頻率操作過程中只被調(diào)用執(zhí)行一次,降低其執(zhí)行頻率戏溺。
   作用:減少代碼執(zhí)行次數(shù)渣蜗,提升網(wǎng)頁性能
   應(yīng)用場(chǎng)景:oninput、onmousemove旷祸、onscroll耕拷、onresize等高頻事件
   (這類事件雖然高頻,但是還有一個(gè)特點(diǎn)托享,就是人為觸發(fā)的骚烧,就是可能快可能慢;
   但是像視頻或音樂的播放闰围,這種持續(xù)高頻但是又不受人為控制的赃绊,這種事件不適合用函數(shù)防抖,
   而要用函數(shù)節(jié)流羡榴。因?yàn)楹瘮?shù)防抖是如果不停的觸發(fā)碧查,定時(shí)器會(huì)不停的被清除創(chuàng)建,
   定時(shí)器里面的函數(shù)(除最后一次定時(shí)器創(chuàng)建的會(huì)被執(zhí)行外)有可能永遠(yuǎn)都不會(huì)執(zhí)行;
   而函數(shù)節(jié)流則是加了雙重開關(guān)忠售,定時(shí)器中函數(shù)至少執(zhí)行過才會(huì)被清除然后再次設(shè)定传惠,所以里面的函數(shù)一定會(huì)執(zhí)行,
   所以總體會(huì)被執(zhí)行n次稻扬。所以說函數(shù)節(jié)流應(yīng)用范圍更廣)
   */
  function debounce(fn,delay) {
      let timeId = null;
      return function (params) {
          let args = arguments;
          let self = this;
          timeId && clearTimeout(timeId);
          timeId = setTimeout(function(){
              fn.apply(self, args);
          },delay || 1000);
      }
  }


  // ******函數(shù)節(jié)流******
  function throttle(fn,delay) {
      let timeId = null;
      let flag = true;
      return function () {
          if(!flag) return;
          flag = false;
          timeId && clearTimeout(timeId);

          let args = arguments;
          let self = this;
          timeId = setTimeout(function(){
              flag = true;
              fn.apply(self, args);
          },delay || 1000);
      }
  }


  // ******勻速動(dòng)畫******
  function linearAnimation(ele, attrs) {
      for(let attr in attrs){
          if(!ele.anmTimer) {ele.anmTimer = {}}
          ele.anmTimer[attr] && clearInterval(ele.anmTimer[attr]);
          let styles = ele.currentStyle || getComputedStyle(ele);
          let begin = parseFloat(styles[attr]);
          let suffix = styles[attr].replace(/[^A-z]/ig, '');
          let target = parseFloat(attrs[attr]);
          let step = +((target - begin) * 0.05).toFixed(3);

          ele.anmTimer[attr] = setInterval(function(){
              begin += step;
              if(Math.abs((target - begin).toFixed(2)) <= Math.abs(step)) {
                  clearInterval(ele.anmTimer[attr]);
                  begin = target;
              }
              ele.style[attr] = begin + suffix;

          },100);

      }

  }


  // ******緩動(dòng)動(dòng)畫******
  function easeAnimation(ele,attrs) {
      for(let attr in attrs){
          if(!ele.anmTimer) {ele.anmTimer = {}}
          ele.anmTimer[attr] && clearInterval(ele.anmTimer[attr]);
          let styles = ele.currentStyle || getComputedStyle(ele);
          let begin = parseFloat(styles[attr]);
          let suffix = ("" + styles[attr]).replace(/[^A-z]/gi, '');
          let target = parseFloat(attrs[attr]);
          let minSpace = Math.abs(((target - begin) * 0.02).toFixed(3));

          ele.anmTimer[attr] = setInterval(function () {
              step = +((target - begin) * 0.3).toFixed(3);
              
              if((Math.abs(+(target - begin).toFixed(2)) <= minSpace)){
                  ele.style[attr] = target + suffix;
                  clearInterval(ele.anmTimer[attr]);
                  return
              }
              begin += step;
              ele.style[attr] = begin + step + suffix;

          },100);
      }
  }


  // ******格式化播放次數(shù)******
  function fmtPlayCount(playCount){// 格式化推薦歌單后臺(tái)數(shù)據(jù)中的播放次數(shù)數(shù)據(jù)
      if((playCount + "").length > 8) {
          return (playCount/100000000).toFixed(1) + '億';
      }else if((playCount + "").length > 4) {
          return (playCount / 10000).toFixed(1) + '萬';
      }else {
          return playCount;
      }
  }
  
  
  // ******創(chuàng)建進(jìn)度條******
  class Progress {
      constructor(bar) {
          this.oBar = isDOM(bar) ? bar : document.querySelector(bar);
          const oBarstyles = this.oBar.currentStyle || getComputedStyle(this.oBar)
          if (oBarstyles.backgroundColor === 'rgba(0, 0, 0, 0)') {
            this.oBar.style.backgroundColor = '#aaa';
          }
          // this.oBar.style.cssText = `background: #aaa;`;
          this.oLine = document.createElement('div');
          this.oDot = document.createElement('div');
          this.oLine.appendChild(this.oDot);
          this.oBar.innerHTML = '';
          this.oBar.appendChild(this.oLine);
          this.linePercent = 0 // 當(dāng)前進(jìn)度條百分比
          this.callBefores = [] // 事件之前要執(zhí)行的方法數(shù)組
          this.callBacks = [] // 事件之后要執(zhí)行的方法

          setTimeout(() => {
              // 延遲獲取寬度卦方,防止沒有渲染完獲取的不準(zhǔn)確。
              this.barHeight = parseInt(getComputedStyle(this.oBar).height);
              this.barWidth = parseInt(getComputedStyle(this.oBar).width);

              // 初始化前景樣式
              // this.oLine.style.cssText = `width: 0; height: 100%; background: #eee; position: relative;`;
              this.oLine.style.width = '0';
              this.oLine.style.height = '100%';
              this.oLine.style.backgroundColor = '#eee';
              this.oLine.style.position = 'relative';
              // 初始化小圓點(diǎn)樣式
              // this.oDot.style.cssText = `width: ${this.barHeight * 2}px; height: ${this.barHeight * 2}px; background: #eee; position: absolute; right: ${-this.barHeight / 2}px; top: ${- this.barHeight / 2}px; border-radius: 50%;`;
              this.oDot.style.width = `${this.barHeight * 2}px`;
              this.oDot.style.height = `${this.barHeight * 2}px`;
              this.oDot.style.backgroundColor = '#eee';
              this.oDot.style.position = 'absolute';
              this.oDot.style.right = `${-this.barHeight / 2}px`;
              this.oDot.style.top = `${- this.barHeight / 2}px`;
              this.oDot.style.borderRadius = '50%';

          }, 200);
      }
      // 因?yàn)樵卦赿isplay: none狀態(tài)下是無法一定能通過getComputedStyle獲取到數(shù)據(jù)的泰佳,有可能會(huì)返回auto,所以其他方法如果用到寬度的話盼砍,
      // 需要先判斷一下,沒有值得話逝她,需要等待獲取浇坐。
      getSureData(cb,params) {
          let that = this;
          // if(that.barWidth >= 0) return;
          
          return new Promise(function(resolve, reject){
              if(that.barWidth >= 0) {
                  resolve(that.barWidth);
              }else {
                  let timer = setInterval(function(){
                      that.barWidth = parseInt(getComputedStyle(that.oBar).width);
                      if(that.barWidth >= 0) {
                          clearInterval(timer);
                          // cb.call(that,params);
                          resolve(that.barWidth)
                      }
                  }, 200);
              }
          });
      }

      // 設(shè)置進(jìn)度條的顏色及圓角樣式(背景色、漸變背景色汽绢、前景色吗跋、漸變前景色、圓點(diǎn)色宁昭、徑向漸變圓點(diǎn)色跌宛、進(jìn)度條是否圓角)
      barCss ({barCor, barGradCor, lineCor, lineGradCor, dotCor, dotRadiCor, cirRadius}) {
        // 因?yàn)閷捀呤茄舆t獲取的,并且同時(shí)重置了樣式积仗,所以樣式設(shè)置必須在獲取寬高以后設(shè)置疆拘,否則會(huì)被再次重置
        this.getSureData().then((barWidth) => {
          barCor && (this.oBar.style.background = barCor);
          barGradCor && (this.oLine.style.background = `linear-gradient(${barGradCor})`);
          lineCor && (this.oLine.style.background = lineCor);
          lineGradCor && (this.oLine.style.background = `linear-gradient(${lineGradCor})`);
          dotCor && (this.oDot.style.background = dotCor);
          dotRadiCor && (this.oDot.style.background = `radial-gradient(${dotRadiCor})`);
          if(cirRadius) {
              this.oBar.style.borderRadius = this.barHeight / 2 + 'px';
              this.oLine.style.borderRadius = this.barHeight / 2 + 'px';
          }else {
              this.oBar.style.borderRadius = 0;
              this.oLine.style.borderRadius = 0;
          }
        })
      }

      // 注:要想拖動(dòng)小圓點(diǎn)必須要執(zhí)行該初始化事件方法
      initEvents ({callBefore, callBack} = {}) {
          // let isPcClient = isPc();
          // console.log(isPcClient);
          // let downEventName = isPcClient ? 'mousedown' : 'touchstart';
          // let moveEventName = isPcClient ? 'mousemove' : 'touchmove';
          // let upEventName = isPcClient ? 'mousedown' : 'touchend';

          // if(!(this.barWidth >= 0)) {
          //     this.getSureData(this.initEvents,{callBefore, callBack});
          //     return;
          // } ;

          let that = this;
          this.getSureData().then(function(){
              if(isPc()) {
                  that.oDot.onmousedown = function(event){
                      event = event || window.event;
                      // 回調(diào)函數(shù)里面兩個(gè)參數(shù):一個(gè)是當(dāng)前進(jìn)度條比例,一個(gè)是當(dāng)前進(jìn)度條寬度
                      // callBefore && callBefore(that.linePercent, that.oLine.style.width);
                      callBefore && that.callBefores.push(callBefore)
                      if(that.callBefores.length) {
                        that.callBefores.forEach((fn) => {
                          fn.call(that, that.linePercent, that.oLine.style.width)
                        })
                      }
                      let oldX = event.pageX;
                      let oldLineWidth = parseInt(getComputedStyle(that.oLine).width);
                      document.onmousemove = function(event){
                          let curLineWidth = oldLineWidth + (event.pageX - oldX);
                          if (curLineWidth < 0) {
                              curLineWidth = 0
                          }else if(curLineWidth > that.barWidth) {
                              curLineWidth = that.barWidth;
                          }
                          that.oLine.style.width = curLineWidth + 'px';
                          that.linePercent = parseInt(getComputedStyle(that.oLine).width) / that.barWidth
                      }
                      document.onmouseup = function(event){
                        // 回調(diào)函數(shù)里面兩個(gè)參數(shù):一個(gè)是當(dāng)前進(jìn)度條比例寂曹,一個(gè)是當(dāng)前進(jìn)度條寬度
                        // callBack && callBack(that.linePercent, that.oLine.style.width);
                        callBack && that.callBacks.push(callBack)
                        if(that.callBacks.length) {
                          that.callBacks.forEach((fn) => {
                            fn.call(that, that.linePercent, that.oLine.style.width)
                          })
                        }
                        document.onmousemove = null;
                        document.onmouseup = null;
                      }
                      if(event.stopPropagation) {
                          event.stopPropagation();
                      }else {
                          event.cancelBubble = true;
                      }
                  }
  
              }else {
                  that.oDot.ontouchstart = function(event){
                      // 回調(diào)函數(shù)里面兩個(gè)參數(shù):一個(gè)是當(dāng)前進(jìn)度條比例哎迄,一個(gè)是當(dāng)前進(jìn)度條寬度
                      // callBefore && callBefore(that.linePercent, that.oLine.style.width);
                      callBefore && this.callBefores.push(callBefore)
                      if(that.callBefores.length) {
                        that.callBefores.forEach((fn) => {
                          fn.call(that, that.linePercent, that.oLine.style.width)
                        })
                      }
                      let oldX = event.targetTouches[0].pageX;// 注意這里采用pageX不要用sreenX;否則有些問題隆圆;
                      let oldLineWidth = parseFloat(getComputedStyle(that.oLine).width);
                      document.ontouchmove = function(event){
                          let curLineWidth = (event.targetTouches[0].pageX - oldX) + oldLineWidth;// 注意這里采用pageX不要用sreenX漱挚;否則有些問題;
                          if (curLineWidth < 0) {
                              curLineWidth = 0
                          }else if(curLineWidth > that.barWidth) {
                              console.log(that.barWidth, '寬度');
                              curLineWidth = that.barWidth;
                          }
                          that.oLine.style.width = curLineWidth + 'px';
                          that.linePercent = parseInt(getComputedStyle(that.oLine).width) / that.barWidth
                      }
                      document.ontouchend = function(event){
                          // 回調(diào)函數(shù)里面兩個(gè)參數(shù):一個(gè)是當(dāng)前進(jìn)度條比例渺氧,一個(gè)是當(dāng)前進(jìn)度條寬度
                          // callBack && callBack(that.linePercent, that.oLine.style.width);
                          callBack && that.callBacks.push(callBack)
                          if(that.callBacks.length) {
                            that.callBacks.forEach((fn) => {
                              fn.call(that, that.linePercent, that.oLine.style.width)
                            })
                          }
                          document.ontouchmove = null;
                          document.ontouchend = null;
                      }
                  }
                  
              }
              
              that.oBar.addEventListener('click', function(event){
                  // 回調(diào)函數(shù)里面兩個(gè)參數(shù):一個(gè)是當(dāng)前進(jìn)度條比例旨涝,一個(gè)是當(dāng)前進(jìn)度條寬度
                  // callBefore && callBefore(that.linePercent, that.oLine.style.width);
                  callBefore && that.callBefores.push(callBefore)
                  if(that.callBefores.length) {
                    that.callBefores.forEach((fn) => {
                      fn.call(that, that.linePercent, that.oLine.style.width)
                    })
                  }
                  event = event || window.event;
                  if(event.target !== that.oDot) {// 防止點(diǎn)擊“點(diǎn)”的時(shí)候也執(zhí)行
                      that.oLine.style.width =  event.offsetX + 'px';
                      that.linePercent = parseInt(getComputedStyle(that.oLine).width) / that.barWidth
                      // 回調(diào)函數(shù)里面兩個(gè)參數(shù):一個(gè)是當(dāng)前進(jìn)度條比例,一個(gè)是當(dāng)前進(jìn)度條寬度
                      // callBack && callBack(that.linePercent, that.oLine.style.width);
                      callBack && that.callBacks.push(callBack)
                      if(that.callBacks.length) {
                        that.callBacks.forEach((fn) => {
                          fn.call(that, that.linePercent, that.oLine.style.width)
                        })
                      }
                  }
                  if(event.stopPropagation) {
                      return event.stopPropagation();
                  }else {
                      event.cancelBubble = true;
                  }
              })
          })
          
      }


      // 額外添加事件
      addEvents ({callBefore, callBack}) {
        typeof(callBefore) === 'function' && this.callBefores.push(callBefore);
        typeof(callBack) === 'function' && this.callBacks.push(callBack);
      }


      // 更新進(jìn)度條進(jìn)度的方法(參數(shù)寬度既可以是百分比也可以是決定寬度值)
      updateProgress (width, callBefore, callBack) {
          // if(!(this.barWidth >= 0)) {
          //     this.getSureData(this.updateProgress,width);
          //     return;
          // } ;
          let that = this;
          this.getSureData().then(function(){
              callBefore && callBefore(that.linePercent / that.barWidth, that.oLine.style.width);
              width = parseFloat(width);
              if (width <= 1) {
                that.linePercent = width;
                that.oLine.style.width = that.barWidth * width + 'px';
              }else {
                that.linePercent = width / that.barWidth;
                that.oLine.style.width = width + 'px';
              }
              callBack && callBack(that.linePercent, that.oLine.style.width);
          })
      }
  } 


  // ******判斷是不是電腦端******
  function isPc() {
      return !/iPhone|Android|Mobile/.test(window.navigator.userAgent);
  }


  // ******創(chuàng)建高亮關(guān)鍵字方法******
  function lightKeywords(keyword, html) {
      let reg = new RegExp(`(${keyword})`, 'g');
      return html.replace(reg, "<span class='keyword'>$1</span>");
  }


  // ******Storage的存嚷卤场(數(shù)組形式)******
  ZLLocalData = {
      getSession: function(key) {
          let str = sessionStorage.getItem(key);
          if (!str) return
          let arr = JSON.parse(str);
          return arr;
      },
      setSession: function(key, value, flag) {
          // flag為true表示完全添加和覆蓋,否則就是差異添加
          if (flag) {
            localStorage.setItem(key, JSON.stringify(value))
            return
          }
          value = JSON.stringify(value);
          let storage = sessionStorage.getItem(key);
          if(storage && storage.length > 2) {
              let index = storage.indexOf(value);
              if(index === 1) return;
              if(index > -1) {
                  storage = storage.replace(',' + value, "");
              }
              storage = storage.replace('[','[' + value + ',');
          }else {
              storage = `[${value}]`;
          }
          sessionStorage.setItem(key, storage);
      },
      removeSession: function (key, value) {
          // 如果flag為真表示完全刪除白华,否則是差異刪除
          if (flag) {
            localStorage.removeItem(key)
            return
          }
          
          if(value) {
              value = JSON.stringify(value);
              let storage = sessionStorage.getItem(key);
              let index = storage.indexOf(value);
              if(index < 0) return;
              storage = storage.replace(value, "");
              storage = storage.replace(',,', ",");
              storage = storage.replace(/^\[,/g, "[");
              storage = storage.replace(/,\]$/g, "]");
              if(storage !== '[]') {
                  sessionStorage.setItem(key, storage);
                  return;
              }
          } 
          sessionStorage.removeItem(key);
      },


      getStorage: function(key) {
          let str = localStorage.getItem(key);
          if (!str) return
          let arr = JSON.parse(str);
          return arr;
      },

      setStorage: function(key, value, flag) {
        // flag為true表示完全添加和覆蓋,否則就是差異添加
          if (flag) {
            localStorage.setItem(key, JSON.stringify(value))
            return
          }

          value = JSON.stringify(value);
          let storage = localStorage.getItem(key);
          if(storage && storage.length > 2) {
              let index = storage.indexOf(value);
              if(index === 1) return;
              if(index > -1) {
                  storage = storage.replace(',' + value, "");
              }
              storage = storage.replace('[','[' + value + ',');
          }else {
              storage = `[${value}]`;
          }
          localStorage.setItem(key, storage);
      },

      removeStorage: function (key, value, flag) {
          // 如果flag為真表示完全刪除,否則是差異刪除
          if (flag) {
            localStorage.removeItem(key)
            return
          }

          if(value) {
              value = JSON.stringify(value);
              let storage = localStorage.getItem(key);
              let index = storage.indexOf(value);
              if(index < 0) return;
              storage = storage.replace(value, "");
              storage = storage.replace(',,', ",");
              storage = storage.replace(/^\[,/g, "[");
              storage = storage.replace(/,\]$/g, "]");
              if(storage !== '[]') {
                  localStorage.setItem(key, storage);
                  return;
              }
          } 
          localStorage.removeItem(key);
      }
  }


  // ******音樂播放器******(需要jquery支持)
  class ZLAudio {
      constructor(musicLists) {// 歌曲對(duì)象數(shù)組贩耐,{id:99, song:"生如夏花", songer: '樸樹', url: '', lyricStr(可選): '歌詞字符串'}
          this.oAudio = document.createElement('audio');
          this.oAudio.innerText = '您的瀏覽器不支持播放';
          // $('body').append(this.oAudio);
          this.$Audio = $(this.oAudio);
          this.isCanPlay = false;
          this.playMode = 'loop';
          this.lyricLiHeight = 0;
          this.musicProgress = null;
          this.currentTime = 0; // 這里寫出來是為了照顧vue中弧腥,方便watch監(jiān)聽,因?yàn)槿绻獑为?dú)監(jiān)聽一個(gè)對(duì)象的一個(gè)屬性潮太,該對(duì)象初始的時(shí)候就要有該屬性
          this.fmtCurrentTime = 0;
          this.callBacks = [] // 存儲(chǔ)跟隨播放要執(zhí)行的所有回調(diào)函數(shù)
          
          if(musicLists) {this.initMusicLists(musicLists)}
          this._listenCanPlay();
      }

      // 監(jiān)聽歌曲是否可以播放(內(nèi)部調(diào)用)
      _listenCanPlay(canPlay) {
          //監(jiān)聽歌曲加載
          // this.oAudio.oncanplay = null;
          let that = this;
          // 不用oncanplay監(jiān)聽管搪,因?yàn)樘O果的safari瀏覽器不會(huì)自動(dòng)加載歌曲資源
          // this.oAudio.oncanplay = function(){
          this.oAudio.ondurationchange = function(){
              // 初始化音樂時(shí)長(zhǎng)
              that.fmtDuration = dateFmt('mm:ss', that.oAudio.duration * 1000).fmtTimeStr;
              that.duration = that.oAudio.duration;
              that.isCanPlay = true;
              canPlay && canPlay(that.duration);
              that.oAudio.play();//播放音樂
          };
      }

      // 監(jiān)聽歌曲播放
      listenPlay(cb) {
          let that = this;
          this.oAudio.ontimeupdate = function(){
              that.currentTime = that.oAudio.currentTime;
              that.fmtCurrentTime = dateFmt('mm:ss', that.oAudio.currentTime * 1000).fmtTimeStr;
              if(that.musicProgress) {
                  that.musicProgress.updateProgress(that.oAudio.currentTime / that.oAudio.duration);
              }

              cb && that.addEvents(cb);
              if (that.callBacks.length) {
                that.callBacks.forEach(fn => {
                  fn.call(that, that.fmtCurrentTime, that.fmtDuration)
                });
              }
          }
      }


      // 額外添加跟隨播放要執(zhí)行的回調(diào)函數(shù)
      addEvents (callBack) {
        typeof(callBack) === 'function' && this.callBacks.push(callBack);
      }

      // 加載(播放)歌曲
      loadMusic(curSongId,url,cb) {
          if(this.curMusicId && this.curMusicId === curSongId) return;
          let curSongIndex = this.findSongIndex(curSongId);
          let that = this;
          url = this.musicLists[curSongIndex].url || url;
          if (!url) return
          if(typeof url === 'string') {
              that.oAudio.src = url;
          }else if(url.constructor.name === 'Array') {//{url: '', type: ''}
              let musicHtml = '';
              url.forEach(function(ele){
                  musicHtml += `<source src="${ele.url}" type="audio/${ele.type}">`;
              });
              that.oAudio.html(musicHtml);
              that.oAudio.load();
          }
          that.curMusicId = curSongId;
          cb && cb(curSongId);
      }


      // 監(jiān)聽歌曲是否播放完
      listenPlayEnd(cb) {
          this.oAudio.onended = cb;
      }

      // 初始化音樂列表
      initMusicLists(musicLists) {
          this.musicLists = musicLists;
          this.curSongId = this.musicLists[0].id;
      }
      
      // 歌詞處理
      handleLyrics(curSongId,lyricStr,cb) {
          if(this.curLyricId && this.curLyricId === curSongId) return;
          let that = this;
          let lyricsObj = _lyricHandle(lyricStr);
          let lyricsHtml = "";
          let i = 0;
          for(let key in lyricsObj) {
              let tiemStr = dateFmt('mm:ss', + key * 1000 ).fmtTimeStr;
              lyricsHtml += `<li id="zl-${key}" time=${tiemStr} offset=${i}>${lyricsObj[key]}</li>`;
              i++;
          }
          that.lyrics = lyricsObj;
          that.lyricsHtml = lyricsHtml;
          that.curLyricId = curSongId;
          cb && cb(lyricObj);
          return lyricsHtml;
          
          //將歌詞字符串轉(zhuǎn)化為對(duì)象(內(nèi)部調(diào)用)
          function _lyricHandle(lyricStr){
              let reg = /\[(.+)\](.+)/g;
              let lyricObj = {};
              lyricStr.replace(reg, function($,$1,$2){
                  let time = $1.substr(0,2) * 60 + Math.round(+$1.substr(3));
                  lyricObj[time] = $2.trim();
              })
              return lyricObj;
          }
      }
      // 同步高亮當(dāng)前歌詞
      lightActiveLyric (lyricWrapper, className, color) {
        this.oLyricWrapper = isDOM(lyricWrapper) ? lyricWrapper : document.querySelector(lyricWrapper);
        className = className || 'active';
        if (color && typeof(color) === 'string') {
          this.oLyricWrapper.style.color = color;
        }
        this.$Audio.on('timeupdate', () => {
          console.log(this.currentTime)
          console.log('#zl-' + Math.round(this.currentTime))
          $('#zl-' + Math.round(this.currentTime)).addClass(className).siblings().removeClass(className)
        })

      }

      // 初始化音量條
      initVolumeProgress(selector,cb,muteBtn) {
          this.volumeProgress = new Progress(selector);
          this.oAudio.volume = 0.5;
          this.volumeProgress.updateProgress(this.oAudio.volume);
          let that = this;
          muteBtn && $(muteBtn).click(function(){//設(shè)置靜音按鈕的點(diǎn)擊事件
              if(that.oAudio.volume === 0){
                  that.oAudio.volume = that.volume;
              }else {
                  that.volume = that.oAudio.volume;
                  that.oAudio.volume = 0;
              }
              return false;
          });
          this.volumeProgress.initEvents({callBack: function(value){
              that.oAudio.volume = value;
              that.volume = value;
              cb && cb(that.oAudio.volume);
          }})
          return that.volumeProgress;
      }

      // 初始化音樂進(jìn)度條
      initMusicProgress(selector,cb) {
          this.musicProgress = new Progress(selector);
          let that = this;
          that.musicProgress.initEvents({callBack: function(widthPercent){
              that.oAudio.currentTime = isNaN(that.oAudio.duration) ? 0 : that.oAudio.duration * widthPercent;
              that.currentTime = that.oAudio.currentTime;
              cb && cb(widthPercent);
          }});
          return that.musicProgress;
      }

      // 根據(jù)歌曲索引查找id
      findSongId(index) {
          return this.musicLists[index].id;
      }

      // 根據(jù)歌曲id查找索引
      findSongIndex(songId) {
          return this.musicLists.findIndex(function(ele){
              return ele.id === songId;
          })
      }
  } 




  window.isDOM = isDOM; // 判斷是否是dom對(duì)象
  window.dateFmt = dateFmt; // 格式化日期或者時(shí)長(zhǎng)
  window.debounce = debounce; // 函數(shù)防抖
  window.throttle = throttle; // 函數(shù)節(jié)流
  window.linearAnimation = linearAnimation; // 線性動(dòng)畫
  window.easeAnimation = easeAnimation; // 緩動(dòng)動(dòng)畫
  window.fmtPlayCount = fmtPlayCount; // 格式化播放量
  window.Progress = Progress; // 進(jìn)度條對(duì)象
  window.isPc = isPc; // 判斷是否電腦端
  window.lightKeywords = lightKeywords; // 高亮關(guān)鍵字
  window.ZLLocalData = ZLLocalData; // 本地存儲(chǔ)方法
  window.ZLAudio = ZLAudio; // 音頻播放器對(duì)象
  window.getRandomInt = getRandomInt; // 獲取隨機(jī)整數(shù)
})();

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抛蚤,更是在濱河造成了極大的恐慌台谢,老刑警劉巖寻狂,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岁经,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蛇券,警方通過查閱死者的電腦和手機(jī)缀壤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纠亚,“玉大人塘慕,你說我怎么就攤上這事〉侔” “怎么了图呢?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)骗随。 經(jīng)常有香客問我蛤织,道長(zhǎng),這世上最難降的妖魔是什么鸿染? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任指蚜,我火速辦了婚禮,結(jié)果婚禮上涨椒,老公的妹妹穿的比我還像新娘摊鸡。我一直安慰自己撩嚼,他們只是感情好间驮,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布碍讨。 她就那樣靜靜地躺著捻艳,像睡著了一般薄辅。 火紅的嫁衣襯著肌膚如雪炸枣。 梳的紋絲不亂的頭發(fā)上摄闸,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天禁漓,我揣著相機(jī)與錄音赢乓,去河邊找鬼忧侧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛牌芋,可吹牛的內(nèi)容都是我干的蚓炬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼躺屁,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼肯夏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤驯击,失蹤者是張志新(化名)和其女友劉穎烁兰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徊都,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沪斟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暇矫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主之。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖李根,靈堂內(nèi)的尸體忽然破棺而出槽奕,到底是詐尸還是另有隱情,我是刑警寧澤房轿,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布粤攒,位于F島的核電站,受9級(jí)特大地震影響囱持,放射性物質(zhì)發(fā)生泄漏夯接。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一洪唐、第九天 我趴在偏房一處隱蔽的房頂上張望钻蹬。 院中可真熱鬧,春花似錦凭需、人聲如沸问欠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顺献。三九已至,卻和暖如春枯怖,著一層夾襖步出監(jiān)牢的瞬間注整,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工度硝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肿轨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓蕊程,卻偏偏與公主長(zhǎng)得像椒袍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藻茂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349