JS操作SVG模拟水滴分离、融合效果
来源:互联网 发布:网络音乐最新排行榜 编辑:程序博客网 时间:2024/06/08 11:45
很多的App应用下拉刷新使用拉拽圆的动态效果来表示下拉过程,很富有表现性;还有QQ的消除红点的过程等,都使用到了这种类似水滴融合的效果。
这种变化的实质是绘制两个圆,然后在两个圆之间利用贝塞尔曲线来描绘弧形,在两个圆的距离随着拖动发生改变时,通过计算数学公式动态地更改曲线的弧度,从而使整个变化过程看起来更加协调。
下面粗略模拟一下这个过程,如果想要更加完美的表现,需要经过精确的计算得出更准确的公式,这里之后补充。
首先我们绘制一下变化过程中的几个过程,如下图:
两个圆之间的粘合部分需要使用二次贝塞尔曲线来绘制。其中弧线的两个端点值和一个中间点,目前使用竖直线和圆的切线交点和两个圆心中点的水平线上偏移一定值的点来简单替代,当然效果不够完美,有待后续优化。例如第二个图的路径写法如下:
<g transform="translate(100,0)"> <circle cx="100" cy="100" r="30" fill="#f59393"></circle> <circle cx="100" cy="150" r="30" fill="#f59393"></circle> <path d="M70,100 Q80,125 70,150 L130,150 Q120,125 130,100 L70,100" fill="#f59393" stroke="black"></path> </g>
在图中标志下路径:
通过模拟上面几个大致的变化过程,得出粗略的公式,绑定点击事件,实现分离、融合效果:
下面是代码:
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>SVG模拟水滴分离、融合效果</title></head><body> <svg width="800" height="400" id="svg"> <g transform="translate(0,0)"> <circle cx="100" cy="110" r="40" fill="#f59393"></circle> </g> <g transform="translate(100,0)"> <circle cx="100" cy="100" r="30" fill="#f59393"></circle> <circle cx="100" cy="150" r="30" fill="#f59393"></circle> <path d="M70,100 Q80,125 70,150 L130,150 Q120,125 130,100 L70,100" fill="#f59393"></path> </g> <g transform="translate(200,0)"> <circle cx="100" cy="98" r="28" fill="#f59393"></circle> <circle cx="100" cy="180" r="28" fill="#f59393"></circle> <path d="M72,100 Q95,140 72,180 L128,180 Q105,140 128,100 L72,100" fill="#f59393"></path> </g> <g transform="translate(300,0)"> <circle cx="100" cy="96" r="26" fill="#f59393"></circle> <circle cx="100" cy="200" r="26" fill="#f59393"></circle> <path d="M74,100 Q110,150 74,200 L126,200 Q90,150 125,100 L74,100" fill="#f59393"></path> </g> <g transform="translate(400,0)"> <circle cx="100" cy="94" r="28" fill="#f59393"></circle> <circle cx="100" cy="220" r="28" fill="#f59393"></circle> </g> <g transform="translate(500,0)" id="g"> <circle id="circle1" cx="100" cy="110" r="40" fill="#f59393"></circle> <circle id="circle2" cx="100" cy="110" r="40" fill="#f59393"></circle> <path id="path" fill="#f59393"></path> </g> <g transform="translate(600,0)" id="g2"> <circle id="circle3" cx="100" cy="94" r="28" fill="#f59393"></circle> <circle id="circle4" cx="100" cy="216" r="28" fill="#f59393"></circle> <path id="path2" fill="#f59393"></path> </g> </svg> <button id="split">分离</button> <button id="split2">合并</button> <script type="text/javascript"> var svg = document.getElementById("svg"); var g = document.getElementById("g"); var circle = document.getElementById("circle1"); var circle2 = document.getElementById("circle2"); var path = document.getElementById("path"); var g2 = document.getElementById("g"); var circle3 = document.getElementById("circle3"); var circle4 = document.getElementById("circle4"); var path2 = document.getElementById("path2"); var button = document.getElementById("split"); var button2 = document.getElementById("split2"); button.onclick = function(){ for(var i=1;i<=40;i++){ (function(i){ setTimeout(function(){ i /=10; var cx = parseInt(circle1.getAttribute("cx")); var cy1 = 102-i*2; var cy2 = 120+(i>2?(i+1)*20:i*30); var r = 32-i*2; var q1 = 65+i*15; var q2 = 135-i*15; //防止弧线交叉 if(q1>=q2+45){ path.setAttribute("d",""); circle1.setAttribute("r",28); circle2.setAttribute("r",28); return; }else{ circle1.setAttribute("cy",cy1); circle1.setAttribute("r",r); circle2.setAttribute("cy",cy2); circle2.setAttribute("r",r); path.setAttribute("d","M"+(cx-r)+",100 Q"+q1+","+((cy1+cy2)/2)+ " "+(cx-r)+","+cy2+" L"+(cx+r)+","+cy2+" Q"+q2+","+((cy1+cy2)/2)+ " "+(cx+r)+",100 L72,100"); } },i*20)})(i); } }; button2.onclick = function(){ for(var i=40;i>=0;i--){ (function(i){ setTimeout(function(){ i /=10; var cx = parseInt(circle3.getAttribute("cx")); var cy1 = 102-i*2; var cy2 = 120+(i>2?(i+1)*20:i*30); var r = 32-i*2; var q1 = 65+i*15; var q2 = 135-i*15; if(i<=0){ circle3.setAttribute("cy",110); circle3.setAttribute("r",40); circle4.setAttribute("cy",110); circle4.setAttribute("r",40); path2.setAttribute("d",""); }else{ //防止弧线交叉 if(q1>=q2+45){ console.log(i) path2.setAttribute("d",""); return; }else{ circle3.setAttribute("cy",cy1); circle3.setAttribute("r",r); circle4.setAttribute("cy",cy2); circle4.setAttribute("r",r); path2.setAttribute("d","M"+(cx-r)+",100 Q"+q1+","+((cy1+cy2)/2)+ " "+(cx-r)+","+cy2+" L"+(cx+r)+","+cy2+" Q"+q2+","+((cy1+cy2)/2)+ " "+(cx+r)+",100 L72,100"); } } },(40-i)*20)})(i); } } </script></body></html>
0 0
- JS操作SVG模拟水滴分离、融合效果
- 7种炫酷HTML5 SVG液态水滴融合分解动画特效
- 多功能用途 Gooey Effects 7种炫酷HTML5 SVG液态水滴融合动画特效
- 水滴效果
- js操作svg
- js操作svg旋转
- ppt实现水滴效果
- ppt实现水滴效果
- Android_实现水滴效果
- 下拉水滴效果
- 使用Hammer.js操作svg
- js操作svg整体缩放
- d3.js-svg的效果及样式
- Android 水滴下落效果View
- 单点触摸实现水滴效果
- svg平移、放大、缩小及js操作svg
- svg平移、放大、缩小及js操作svg
- svg入门:使用js去操作svg图像
- 获取Windows操作系统版本
- 微信网页版协议的java封装
- 倒计时时钟
- 高性能JAVASCRIPT
- 你如何对网站的文件和资源进行优化?
- JS操作SVG模拟水滴分离、融合效果
- 关于android从入门到精通4.1.9范例1出现的闪退的问题
- 原型设计模型(深拷贝浅拷贝)
- Activity intent intent filter 广播接收器的区别
- mysql触发器
- 欢迎使用CSDN-markdown编辑器
- C# 类和结构的区别
- LocalBroadcastManager
- UIBezierPath精讲