123

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              body {
    background-color: whitesmoke;
    margin: 0;
    padding: 0;
}

circle {
    cursor: pointer;
}
            
          
!
            
              (function(name, definition) {
  var sux = this.sux = this.sux || {};

  sux[name] = definition();
})('timingfunction', function() {
  var timingfunction = {};

  /**
   * linear 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.linear = function(p) {
    return p;
  };
  /**
   * swing 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.swing = function(p) {
    return .5 - Math.cos(p * Math.PI) / 2;
  };
  /**
   * easeInQuad 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInQuad = function(p) {
    return Math.pow(p, 2);
  };
  /**
   * easeOutQuad 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutQuad = function(p) {
    return 1 - timingfunction.easeInQuad(1 - p);
  };
  /**
   * easeInOutQuad 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutQuad = function(p) {
    return p < 0.5 ?
      timingfunction.easeInQuad(p * 2) / 2 :
      1 - timingfunction.easeInQuad(p * -2 + 2) / 2;
  };
  /**
   * easeInCubic 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInCubic = function(p) {
    return Math.pow(p, 3);
  };
  /**
   * easeOutCubic 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutCubic = function(p) {
    return 1 - timingfunction.easeInCubic(1 - p);
  };
  /**
   * easeInOutCubic 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutCubic = function(p) {
    return p < 0.5 ?
      timingfunction.easeInCubic(p * 2) / 2 :
      1 - timingfunction.easeInCubic(p * -2 + 2) / 2;
  };
  /**
   * easeInQuart 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInQuart = function(p) {
    return Math.pow(p, 4);
  };
  /**
   * easeOutQuart 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutQuart = function(p) {
    return 1 - timingfunction.easeInQuart(1 - p);
  };
  /**
   * easeInOutQuart 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutQuart = function(p) {
    return p < 0.5 ?
      timingfunction.easeInQuart(p * 2) / 2 :
      1 - timingfunction.easeInQuart(p * -2 + 2) / 2;
  };
  /**
   * easeInQuint 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInQuint = function(p) {
    return Math.pow(p, 5);
  };
  /**
   * easeOutQuint 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutQuint = function(p) {
    return 1 - timingfunction.easeInQuint(1 - p);
  };
  /**
   * easeInOutQuint 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutQuint = function(p) {
    return p < 0.5 ?
      timingfunction.easeInQuint(p * 2) / 2 :
      1 - timingfunction.easeInQuint(p * -2 + 2) / 2;
  };
  /**
   * easeInExpo 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInExpo = function(p) {
    return Math.pow(p, 6);
  };
  /**
   * easeOutExpo 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutExpo = function(p) {
    return 1 - timingfunction.easeInExpo(1 - p);
  };
  /**
   * easeInOutExpo 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutExpo = function(p) {
    return p < 0.5 ?
      timingfunction.easeInExpo(p * 2) / 2 :
      1 - timingfunction.easeInExpo(p * -2 + 2) / 2;
  };
  /**
   * easeInSine 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInSine = function(p) {
    return 1 - Math.cos(p * Math.PI / 2);
  };
  /**
   * easeOutSine 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutSine = function(p) {
    return 1 - timingfunction.easeInSine(1 - p);
  };
  /**
   * easeInOutSine 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutSine = function(p) {
    return p < 0.5 ?
      timingfunction.easeInSine(p * 2) / 2 :
      1 - timingfunction.easeInSine(p * -2 + 2) / 2;
  };
  /**
   * easeInCirc 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInCirc = function(p) {
    return 1 - Math.sqrt(1 - p * p);
  };
  /**
   * easeOutCirc 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutCirc = function(p) {
    return 1 - timingfunction.easeInCirc(1 - p);
  };
  /**
   * easeInOutCirc 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutCirc = function(p) {
    return p < 0.5 ?
      timingfunction.easeInCirc(p * 2) / 2 :
      1 - timingfunction.easeInCirc(p * -2 + 2) / 2;
  };
  /**
   * easeInElastic 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInElastic = function(p) {
    return p === 0 || p === 1 ? p :
      -Math.pow(2, 8 * (p - 1)) * Math.sin(((p - 1) * 80 - 7.5) * Math.PI / 15);
  };
  /**
   * easeOutElastic 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutElastic = function(p) {
    return 1 - timingfunction.easeInElastic(1 - p);
  };
  /**
   * easeInOutElastic 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutElastic = function(p) {
    return p < 0.5 ?
      timingfunction.easeInElastic(p * 2) / 2 :
      1 - timingfunction.easeInElastic(p * -2 + 2) / 2;
  };
  /**
   * easeInBack 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInBack = function(p) {
    return p * p * (3 * p - 2);
  };
  /**
   * easeOutBack 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutBack = function(p) {
    return 1 - timingfunction.easeInBack(1 - p);
  };
  /**
   * easeInOutBack 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutBack = function(p) {
    return p < 0.5 ?
      timingfunction.easeInBack(p * 2) / 2 :
      1 - timingfunction.easeInBack(p * -2 + 2) / 2;
  };
  /**
   * easeInBounce 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInBounce = function(p) {
    var pow2,
      bounce = 4;

    while (p < ((pow2 = Math.pow(2, --bounce)) - 1) / 11) {};
    return 1 / Math.pow(4, 3 - bounce) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - p, 2);
  };
  /**
   * easeOutBounce 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeOutBounce = function(p) {
    return 1 - timingfunction.easeInBounce(1 - p);
  };
  /**
   * easeInOutBounce 函数
   *
   * @param  {Number} p 正常百分比值
   * @return {Number}  换算后的结果
   */
  timingfunction.easeInOutBounce = function(p) {
    return p < 0.5 ?
      timingfunction.easeInBounce(p * 2) / 2 :
      1 - timingfunction.easeInBounce(p * -2 + 2) / 2;
  };

  return timingfunction;
});

(function(name, definition) {
  var sux = this.sux = this.sux || {};

  sux[name] = definition();
})('waterdrop', function() {
  var waterdrop = function() {};

  /**
   * 通过入参,计算组成水滴形状的两条贝塞尔曲线控制点.
   *
   * @method getBezierPoints
   *
   * @param  {Number} x 起始点x轴坐标
   * @param  {Number} y 起始点x轴坐标
   * @param  {Number} deltaX 起始点x轴上的间距
   * @param  {Number} deltaY 起始点y轴上的间距
   * @param  {Number} fromR 起始点的半径
   * @param  {Number} toR 目标点的半径
   * @return {Object} 返回包含x1, y1, x2, y2, ... x8, y8十六个参数,分别代表关键点
   */
  waterdrop.prototype.getBezierPoints = function(x, y, deltaX, deltaY, fromR, toR) {
    var x0, y0, // 目标点的坐标
      dX1, dY1, dX2, dY2, dX3, dY3, dX4, dY4, dX5, dY5, dX6, dY6, dX7, dY7, dX8, dY8, // 偏移量
      dis, // 起始点和目标点的距离
      deltaGarmar, // 切线和y轴的夹角
      alpha, // 两点连线和x轴的夹角
      cosAlpha, sinAlpha;

    // 计算圆2的圆点坐标
    x0 = x + deltaX;
    y0 = y + deltaY;

    // 计算距离
    dis = Math.sqrt(Math.pow((deltaX), 2) + Math.pow((deltaY), 2));
    if (dis < Math.max(fromR, toR)) {
      return {
        x1: x0,
        y1: y0,
        x2: x0,
        y2: y0,
        x3: x0,
        y3: y0,
        x4: x0,
        y4: y0,
        x5: x0,
        y5: y0,
        x6: x0,
        y6: y0,
        x7: x0,
        y7: y0,
        x8: x0,
        y8: y0
      };
    }

    // 计算两点连线的夹角
    // tan函数的角度取值范围[-π/2, π/2], 故对alpha值做第二、第三象限处理
    if (deltaX >= 0) {
      alpha = -Math.atan(deltaY / deltaX) + Math.PI / 2;
    } else {
      alpha = -Math.atan(deltaY / deltaX) + Math.PI * 3 / 2;
    }
    sinAlpha = Math.sin(alpha);
    cosAlpha = Math.cos(alpha);

    // 计算切线和y轴的夹角
    deltaGarmar = Math.asin((fromR - toR) / dis);

    // 四个点的偏移量
    dX1 = fromR * Math.cos(deltaGarmar);
    dY1 = fromR * Math.sin(deltaGarmar);
    dX2 = fromR / Math.cos(Math.PI / 4 - deltaGarmar / 2) * Math.cos(Math.PI / 4 + deltaGarmar / 2);
    dY2 = fromR;
    dX3 = toR;
    dY3 = fromR;
    dX4 = toR;
    dY4 = Math.abs(deltaY);
    dX5 = -dX1;
    dY5 = dY1;
    dX6 = -dX2;
    dY6 = dY2;
    dX7 = -dX3;
    dY7 = dY3;
    dX8 = -dX4;
    dY8 = dY4;

    return {
      x1: x + dX1 * cosAlpha + dY1 * sinAlpha,
      y1: y + dY1 * cosAlpha - dX1 * sinAlpha,
      x2: x + dX2 * cosAlpha + dY2 * sinAlpha,
      y2: y + dY2 * cosAlpha - dX2 * sinAlpha,
      x3: x + dX3 * cosAlpha + dY3 * sinAlpha,
      y3: y + dY3 * cosAlpha - dX3 * sinAlpha,
      x4: x + dX4 * cosAlpha + dY4 * sinAlpha,
      y4: y + dY4 * cosAlpha - dX4 * sinAlpha,
      x5: x + dX5 * cosAlpha + dY5 * sinAlpha,
      y5: y + dY5 * cosAlpha - dX5 * sinAlpha,
      x6: x + dX6 * cosAlpha + dY6 * sinAlpha,
      y6: y + dY6 * cosAlpha - dX6 * sinAlpha,
      x7: x + dX7 * cosAlpha + dY7 * sinAlpha,
      y7: y + dY7 * cosAlpha - dX7 * sinAlpha,
      x8: x + dX8 * cosAlpha + dY8 * sinAlpha,
      y8: y + dY8 * cosAlpha - dX8 * sinAlpha
    };
  }

  return new waterdrop;
});

/* 动画处理函数 */
(function() {
  var ID = null,
    STARTTIME = null,
    DURATION = null,
    CALLBACK = null;

  var step = function(timestamp) {
    if (!STARTTIME) {
      STARTTIME = timestamp;
    }

    var gap = timestamp - STARTTIME,
      precent = gap / DURATION;

    if (CALLBACK) {
      CALLBACK(precent);
    }

    if (gap < DURATION) {
      ID = requestAnimationFrame(step);
    } else {
      ID = null,
        STARTTIME = null,
        DURATION = null,
        CALLBACK = null;
    }
  }

  window.doAnimate = function(fn, duration) {
    if (ID) {
      stopAnimate();
    }

    CALLBACK = fn;
    DURATION = duration;

    requestAnimationFrame(step);
  }

  window.stopAnimate = function() {
    if (ID) {
      cancelAnimationFrame(ID);
    }

    ID = null,
      STARTTIME = null,
      DURATION = null,
      CALLBACK = null;
  }
})();

var IndexBar = function(options) {
  var me = this;
  var circleAssistant, circleMain, pathAssistant1, pathAssistant2;

  me.index = 0;
  me.length = 0;

  // 配置
  me.setOptions(options);

  /* 侵入性代码 */
  // 创建组建区域
  me.component = Snap(me.options.BAR_HALF_WIDTH * 2, 190);

  // 创建posGroup,将占位点放置在posGroup组里面
  me.posGroup = me.component.g();

  // 配置active点
  me.indexGroup = me.component.g();
  // 圆Assistant
  circleAssistant = me.component.circle(me.options.BAR_HALF_WIDTH, me.options.ACTIVE_RADIUS, me.options.EMPTY_RADIUS);
  circleAssistant.attr({
    fill: me.options.ACTIVE_COLOR
  });
  // 圆Main
  circleMain = me.component.circle(me.options.BAR_HALF_WIDTH, me.options.ACTIVE_RADIUS, me.options.ACTIVE_RADIUS);
  circleMain.attr({
    fill: me.options.ACTIVE_COLOR
  });
  // 衔接1
  pathAssistant1 = me.component.path('');
  pathAssistant1.attr({
    fill: me.options.ACTIVE_COLOR
  });
  // 衔接2
  pathAssistant2 = me.component.path('');
  pathAssistant2.attr({
    fill: me.options.ACTIVE_COLOR
  });
  me.indexGroup.add(circleMain, circleAssistant, pathAssistant1, pathAssistant2);

  // 默认添加1个点
  me.addDot();
};

//设置默认属性
IndexBar.prototype.setOptions = function(options) {
    var me = this;

    me.options = { //默认值
      BAR_HALF_WIDTH: 10, // 整个滚动条的一半宽度
      GAP: 28, // 两个点之间的距离
      EMPTY_RADIUS: 4, // 活动点半径
      EMPTY_COLOR: '#3886d0', //'#84bae9',
      ACTIVE_RADIUS: 9, // 目标点半径
      ACTIVE_COLOR: '#3886d0',
      WATER_WIDTH: 1.5, // 水滴线宽度
      WATER_BREAK: 11, // 水滴截断位置
      WATER_RESTRICT: 23, // 水滴形成最大贝塞尔曲线的终点y轴位置(大于大圆半径,小于两圆圆周连直线的间距)
      ANIMATION_TIME: 800, // 水滴动画时间
      TIMING_FUNCTION: 'linear' // 水滴动画时间曲线
    };

    for (var property in options) {
      me.options[property] = options[property];
    }
  },

  // 数据结构
  IndexBar.prototype.index = null;
IndexBar.prototype.length = null;

// 组件对象索引
IndexBar.prototype.component = null;
IndexBar.prototype.posGroup = null;
IndexBar.prototype.indexGroup = null;
IndexBar.prototype.inAnimation = false;

IndexBar.prototype.addDot = function() {
  var me = this;
  var len, circle;

  len = me.length;

  // 绘制圆点
  circle = me.component.circle(me.options.BAR_HALF_WIDTH, len * me.options.GAP + me.options.ACTIVE_RADIUS, me.options.EMPTY_RADIUS);
  circle.attr({
    fill: me.options.EMPTY_COLOR,
    stroke: 'transparent',
    'stroke-width': 10
  });

  circle.click(function() {
    if (!me.inAnimation) {
      var clickCircle = this;

      var activeY = me.index * me.options.GAP + me.options.ACTIVE_RADIUS;
      var y = parseInt(clickCircle.attr('cy'));

      me.moveIndex(y - activeY);
    }
  });

  // 缓存
  me.posGroup.add(circle);
  me.length++;
};

IndexBar.prototype.delDot = function() {
  var me = this;
  var circle;

  // 销毁圆和数据
  circle = me.posGroup[me.length - 1];
  circle.unclick();
  circle.remove();
  me.posGroup.removeData(circle);
  me.length--;

  if (me.index >= me.length && me.length !== 0) {
    me.index--;
  }
};

// 移动index点
IndexBar.prototype.moveIndex = function(realGap, fn) {
  var me = this;

  var pathAssistant1 = me.indexGroup[2],
    pathAssistant2 = me.indexGroup[3],
    circleAssistant = me.indexGroup[1],
    circleMain = me.indexGroup[0];

  var posY = me.index * me.options.GAP + me.options.ACTIVE_RADIUS; // 起始点的y轴坐标

  var direction = realGap / Math.abs(realGap);
  realGap = Math.abs(realGap);

  var step1 = 0.15, // 步骤一的长度,起始点向目标点伸出
    step2 = 0.55, // 步骤二的长度,起始点的辅助点收回到断水点,且目标点的辅助点开始伸出
    step3 = 0.85, // 步骤三的长度,起始点的半径缩小为最小值,且目标点的辅助点开始收回
    step4 = 1; // 步骤四的长度,目标点扩张成最大值

  me.inAnimation = true;
  var smallWaterWidth = 0.8;

  doAnimate(function(p) {
    // 绘制的参数
    var mainR = me.options.EMPTY_RADIUS, // 起始点的半径
      mainY = posY, // 起始点的坐标
      assistantR = me.options.EMPTY_RADIUS, // 目标点的半径
      assistantY = posY + realGap * direction, // 目标点的坐标
      tmpR = me.options.WATER_WIDTH,
      tmpPath1 = '', // 起始点和目标点的路径
      tmpPath2 = ''; // 起始点和目标点的路径

    // 实时参数
    var percent = sux.timingfunction[me.options.TIMING_FUNCTION](p > 1 ? 1 : p), // 百分比参数
      bezier1, //贝塞尔弧线的高度1
      res1, //贝塞尔弧线结果1的暂存
      bezier2, //贝塞尔弧线的高度2
      res2; //贝塞尔弧线结果2的暂存

    // 计算起始点的参数
    if (percent <= step3) {
      // 起始点在[0, step2]时,半径缩小成最小
      if (percent <= step2) {
        mainR = me.options.ACTIVE_RADIUS - percent / step2 * (me.options.ACTIVE_RADIUS - me.options.EMPTY_RADIUS); //起始点半径
      }

      // [0, step1]时,尾巴伸长
      if (percent <= step1) {
        bezier1 = me.options.ACTIVE_RADIUS + (realGap - me.options.ACTIVE_RADIUS - me.options.EMPTY_RADIUS) * (percent / step1); //计算起始点的尾巴
      }
      // (step1, step2]时,尾巴缩短到断开点
      else if (percent <= step2) {
        bezier1 = realGap - (percent - step1) / (step2 - step1) * (realGap - me.options.WATER_BREAK); //计算起始点的尾巴
      }
      // (step2, step3]时,尾巴缩短到圆周上 
      else {
        bezier1 = me.options.WATER_BREAK - ((percent - step2) / (step3 - step2)) * (me.options.WATER_BREAK - me.options.EMPTY_RADIUS); //计算起始点的尾巴
      }
    }

    // 计算目标点的参数
    if (percent > step1) {
      // 目标点在[step1, step4]区间时,半径增长到最大
      assistantR = me.options.EMPTY_RADIUS + (percent - step1) / (step4 - step1) * (me.options.ACTIVE_RADIUS - me.options.EMPTY_RADIUS); // 目标点半径

      if (assistantR < me.options.ACTIVE_RADIUS) {
        // [step1, step2]时,尾巴伸长
        if (percent < step2) {
          bezier2 = me.options.EMPTY_RADIUS + (percent - step1) / (step2 - step1) * (realGap - me.options.WATER_BREAK - me.options.EMPTY_RADIUS); //计算目标点的尾巴
        }
        // (step2, step4]时,尾巴缩回
        else {
          bezier2 = realGap - me.options.WATER_BREAK - ((percent - step2) / (step4 - step2)) * (realGap - me.options.WATER_BREAK - me.options.ACTIVE_RADIUS); //计算目标点的尾巴
        }
      }
    }

    var tmpPercent = (step1 / 3 + step2 * 2 / 3);
    if (percent < step2) {
      if (percent > tmpPercent) {
        tmpR = me.options.WATER_WIDTH - (me.options.WATER_WIDTH - smallWaterWidth) * (percent - tmpPercent) / (step2 - tmpPercent);
      }
    } else {
      tmpR = smallWaterWidth;
    }

    // 计算起始点到辅助点的水滴路径
    if (bezier1 > 0) {
      // 计算直线高度
      var tmpb = posY + bezier1 * direction;

      if (bezier1 > me.options.WATER_RESTRICT) {
        bezier1 = me.options.WATER_RESTRICT;
      }
      res1 = sux.waterdrop.getBezierPoints(me.options.BAR_HALF_WIDTH, mainY, 0, bezier1 * direction, mainR, tmpR);
      tmpPath1 += ' M' + res1.x1 + ',' + res1.y1;
      tmpPath1 += ' C' + res1.x2 + ',' + res1.y2 + ' ' + res1.x3 + ',' + res1.y3 + ' ' + res1.x4 + ',' + res1.y4;
      tmpPath1 += ' V' + tmpb;
      tmpPath1 += ' A' + tmpR + ' ' + tmpR + ', 0, 0, ' + 1 + ', ' + res1.x8 + ' ' + tmpb;
      tmpPath1 += ' V' + res1.y8;
      tmpPath1 += ' C' + res1.x7 + ',' + res1.y7 + ' ' + res1.x6 + ',' + res1.y6 + ' ' + res1.x5 + ',' + res1.y5;
      tmpPath1 += ' L' + res1.x1 + ',' + res1.y1 + ' Z';
    }

    // 计算目标点到辅助点的水滴路径
    if (bezier2 > 0) {
      // 计算直线高度
      var tmpp = posY + (realGap - bezier2) * direction;

      if (bezier2 > me.options.WATER_RESTRICT) {
        bezier2 = me.options.WATER_RESTRICT;
      }
      res2 = sux.waterdrop.getBezierPoints(me.options.BAR_HALF_WIDTH, assistantY, 0, -bezier2 * direction, assistantR, tmpR);
      tmpPath2 += ' M' + res2.x1 + ',' + res2.y1;
      tmpPath2 += ' C' + res2.x2 + ',' + res2.y2 + ' ' + res2.x3 + ',' + res2.y3 + ' ' + res2.x4 + ',' + res2.y4;
      tmpPath2 += ' V' + tmpp;
      tmpPath2 += ' A' + tmpR + ' ' + tmpR + ', 0, 0, ' + 1 + ', ' + res2.x8 + ' ' + tmpp;
      tmpPath2 += ' V' + res2.y8;
      tmpPath2 += ' C' + res2.x7 + ',' + res2.y7 + ' ' + res2.x6 + ',' + res2.y6 + ' ' + res2.x5 + ',' + res2.y5;
      tmpPath2 += ' L' + res2.x1 + ',' + res2.y1 + ' Z';
    }

    // 描绘图形
    circleMain.attr({
      r: mainR,
      cy: mainY
    });
    circleAssistant.attr({
      r: assistantR,
      cy: assistantY
    });
    pathAssistant1.attr({
      path: tmpPath1
    });
    pathAssistant2.attr({
      path: tmpPath2
    });

    // 执行回调
    if (percent >= 1) {
      me.index += realGap * direction / me.options.GAP;
      // 重置数据
      circleMain.attr({
        cy: posY + realGap * direction
      });
      circleAssistant.attr({
        cy: posY + realGap * direction
      });
      me.inAnimation = false;

      // 有回调时,执行回调
      if (fn) {
        fn();
      }
    }
  }, me.options.ANIMATION_TIME);
};

var startX = 0,
  startY = 0,
  deltaX = 0,
  deltaY = 0;

var bar = new IndexBar();

bar.addDot();
bar.addDot();
bar.addDot();
bar.addDot();
bar.addDot();
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console