SVG+JS 实现新版手机QQ的手势消除红点消息的动画

阅读 1653
收藏 50
2016-01-13
原文链接:www.xiaoa.name

下面的配图仅供卖萌

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

以上内容是文章摘要

Paper

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

cute-qq-redpoint

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

原理及部分代码

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

 1 (function(){
 2         'use strict';
 3 
 4         var initCircle = document.getElementById('initCircle');
 5         var finalCircle = document.getElementById('finalCircle');
 6         var aPath = document.getElementById('animationPath');
 7 
 8         var touchFingers; //缓存touches队列
 9 
10         //初始圆坐标
11         var x0 = parseInt(initCircle.getAttribute('cx'));
12         var y0 = parseInt(initCircle.getAttribute('cy'));
13         var r0 = parseInt(initCircle.getAttribute('r'));
14 
15         //最终圆坐标
16         var x1;
17         var y1;
18         var r1 = parseInt(finalCircle.getAttribute('r'));
19 
20         //setter
21         Element.prototype._setter = function (options) {
22             var attr;
23             for(attr in options){
24                 if(options.hasOwnProperty(attr)){
25                     this.setAttribute(attr, options[attr]);
26                 }
27             }
28         };
29 
30         var updateF = function updateTouches(event) {
31             touchFingers = event.touches[0];
32         };
33 
34 
35         var renderThing = function () {
36 
37             x1 = touchFingers.clientX;
38             y1 = touchFingers.clientY;
39 
40             //二次贝赛尔曲线参考点
41             var pX = x0 - ((x0 - x1) / 2);
42             var pY = y0 - ((y0 - y1) / 2);
43 
44             //勾股x,y
45             var _gX = Math.abs(x0 - x1);
46             var _gY = Math.abs(y0 - y1);
47 
48             //勾股定理斜线长度长
49             var longL = Math.sqrt(_gX * _gX + _gY * _gY);
50 
51             var sinX = _gY / longL;
52             var cosX = _gX / longL;
53 
54             //四个点的路径构建
55             var fourPoints = [
56                 'M',
57                 x0 + r0 * sinX,
58                 y0 + r0 * cosX,
59                 'Q',
60                 pX,
61                 pY,
62                 x1 + r1 * sinX,
63                 y1 + r1 * cosX,
64                 'L',
65                 x1 - r1 * sinX,
66                 y1 - r1 * cosX,
67                 'Q',
68                 pX,
69                 pY,
70                 x0 - r0 * sinX,
71                 y0 - r0 * cosX,
72                 'Z'
73             ];
74 
75             finalCircle._setter({
76                 cx: x1,
77                 cy: y1
78             });
79 
80             //设置路径
81             aPath._setter({
82                 d: fourPoints.join(' ')
83             });
84 
85         };
86 
87         document.addEventListener('touchstart', function (e) {
88             e.preventDefault();
89             touchFingers = e.touches[0];
90         });
91 
92         document.addEventListener('touchmove', function (e) {
93             e.preventDefault(); //屏蔽掉默认的滚动行为
94             updateF(e);
95             renderThing();
96         });
97 
98 
99     }());

演示

用手机打开 codepen在线Demo

TODO

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

Github

源码地址

评论