Fork me on GitHub
COLORFUL 有个骚年路过这里
2015 - 03 - 05

下面的配图仅供卖萌

很久没有写博客了,今天给大家带来一个小折腾。 虽然说是小折腾,但还是废了不少劲,某位大神的博客写得好: 前端工程师要想脱颖而出,就要拿出草稿纸,所以有了如下这个丑陋无比的配图:

Paper

此次折腾的相关信息如下:

cute-qq-redpoint

SVG+JS实现新版手机QQ的手势消除红点消息的动画。 可以打开手机QQ,在底部菜单消息一栏的红点上进行拖拽体验。 本插件欲实现的就是这个效果。

原理及部分代码

做的比较粗糙,但是基本效果已经实现了。 通过计算草稿中四个坐标位置,然后在touchmove中更新path d即可,两条二次贝塞尔曲线是关键。 二次贝塞尔曲线的参考坐标可以轻松得出: 两个圆心相连线的中心即为该参考点。 故得到代码如下:

(function(){
  'use strict';

  var initCircle = document.getElementById('initCircle');
  var finalCircle = document.getElementById('finalCircle');
  var aPath = document.getElementById('animationPath');

  var touchFingers; //缓存touches队列

  //初始圆坐标
  var x0 = parseInt(initCircle.getAttribute('cx'));
  var y0 = parseInt(initCircle.getAttribute('cy'));
  var r0 = parseInt(initCircle.getAttribute('r'));

  //最终圆坐标
  var x1;
  var y1;
  var r1 = parseInt(finalCircle.getAttribute('r'));

  //setter
  Element.prototype._setter = function (options) {
      var attr;
      for(attr in options){
          if(options.hasOwnProperty(attr)){
              this.setAttribute(attr, options[attr]);
          }
      }
  };

  var updateF = function updateTouches(event) {
      touchFingers = event.touches[0];
  };


  var renderThing = function () {

      x1 = touchFingers.clientX;
      y1 = touchFingers.clientY;

      //二次贝赛尔曲线参考点
      var pX = x0 - ((x0 - x1) / 2);
      var pY = y0 - ((y0 - y1) / 2);

      //勾股x,y
      var _gX = Math.abs(x0 - x1);
      var _gY = Math.abs(y0 - y1);

      //勾股定理斜线长度长
      var longL = Math.sqrt(_gX * _gX + _gY * _gY);

      var sinX = _gY / longL;
      var cosX = _gX / longL;

      //四个点的路径构建
      var fourPoints = [
          'M',
          x0 + r0 * sinX,
          y0 + r0 * cosX,
          'Q',
          pX,
          pY,
          x1 + r1 * sinX,
          y1 + r1 * cosX,
          'L',
          x1 - r1 * sinX,
          y1 - r1 * cosX,
          'Q',
          pX,
          pY,
          x0 - r0 * sinX,
          y0 - r0 * cosX,
          'Z'
      ];

      finalCircle._setter({
          cx: x1,
          cy: y1
      });

      //设置路径
      aPath._setter({
          d: fourPoints.join(' ')
      });

  };

  document.addEventListener('touchstart', function (e) {
      e.preventDefault();
      touchFingers = e.touches[0];
  });

  document.addEventListener('touchmove', function (e) {
      e.preventDefault(); //屏蔽掉默认的滚动行为
      updateF(e);
      renderThing();
  });
}());

演示

用手机打开 codepen在线Demo

TODO

  1. 实现弹性系数K,模拟拉断的情况,加入初始圆的半径缩小控制
  2. 插件化处理

Github

源码地址