All files / fx smoothScrollTo.js

90.63% Statements 29/32
52.94% Branches 9/17
100% Functions 4/4
90.63% Lines 29/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75                              1x     1x   1x           1x 1x 1x     1x   1x   1x 1x 1x 1x 1x 1x 1x         1x 18x 18x 18x   18x 18x     18x 18x     18x   18x   18x         1x 1x       1x  
/**
 * 平滑滚动到某个元素,只进行垂直方向的滚动
 * - requires jQuery/Zepto
 * @method fx/smoothScrollTo
 * @param {Object} node 目标DOM元素
 * @param {Object} spec 选项
 * @param {Number} [spec.delta=0] 目标滚动位置与目标元素顶部的间距,可以为负值
 * @param {Number} [spec.maxDelay=3000] 动画执行时间限制(ms),动画执行超过此时间则直接停止,立刻滚动到目标位置
 * @param {Function} [options.callback] 滚动完成的回调函数
 * @example
 * var $smoothScrollTo = require('@spore-ui/kit/packages/fx/smoothScrollTo');
 * // 滚动到页面顶端
 * $smoothScrollTo(document.body);
 */
 
var $assign = require('../obj/assign');
 
function smoothScrollTo(node, spec) {
  var $ = window.$ || window.Zepto || window.jQuery;
 
  var conf = $assign({
    delta: 0,
    maxDelay: 3000,
    callback: null,
  }, spec);
 
  var offset = $(node).offset();
  var target = offset.top + conf.delta;
  var callback = conf.callback;
 
  var prevStep;
  var stayCount = 3;
 
  var timer = null;
 
  var stopTimer = function () {
    Eif (timer) {
      clearInterval(timer);
      timer = null;
      window.scrollTo(0, target);
      Eif ($.isFunction(callback)) {
        callback();
      }
    }
  };
 
  timer = setInterval(function () {
    var sTop = $(window).scrollTop();
    var delta = sTop - target;
    Iif (delta > 0) {
      delta = Math.floor(delta * 0.8);
    } else Eif (delta < 0) {
      delta = Math.ceil(delta * 0.8);
    }
 
    var step = target + delta;
    Iif (step === prevStep) {
      stayCount -= 1;
    }
    prevStep = step;
 
    window.scrollTo(0, step);
 
    Iif (step === target || stayCount <= 0) {
      stopTimer();
    }
  }, 16);
 
  setTimeout(function () {
    stopTimer();
  }, conf.maxDelay);
}
 
module.exports = smoothScrollTo;