【AnimeJs】——仿Animejs徒手实现SVG动画
我们一般会引入anime.js来改变svg动画,但是anime.js源码有一千多行,但我们只需要修改svg这部分的时候,可以通过我们自己手写一段代码来实现svg动画,来优化性能。
首先来看先anime.js是如何改变svg动画:
1、在script标签中引入anime.js:<script src="anime.js"></script>;
2、svg中有path属性,通过改变path中的d、fill、stroke来改变动画效果。
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head><body><svg class="social" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path class="path"style="fill:#3b5998;fill-rule:evenodd;stroke:#3b5998;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"d="m 41.416254,90 c -0.327378,-7.4702 0.20833,-32.7284 0,-39.901 -5.386902,-0.2083 -4.521603,0.3274 -9.848987,0 0.20833,-5.50595 0.36436,-7.66666 0.126269,-13.32142 4.646472,0.0181 3.439989,-0.009 9.848987,-0.1894 0.09586,-3.7736 0.133082,-3.0791 0.126269,-7.38674 0.18259,-3.73943 -0.486609,-10.54308 4.293149,-14.96288 4.779758,-4.4198 13.606811,-3.64808 22.223356,-3.53554 -0.04417,5.73754 -0.03936,9.37986 0,12.87945 -5.049924,0.46388 -7.309188,-0.33689 -10.85914,1.26269 -1.403378,3.17794 -1.569601,4.80531 -1.262691,11.93242 3.147964,-0.13336 8.201788,-0.1378 12.626907,0 -0.995158,6.00899 -0.948285,7.62376 -1.767767,13.06882 -3.676625,0.088 -5.605721,-0.1488 -11.111678,0 -0.148814,6.756 0.357147,33.0107 0,40.1536 -6.428576,0.1786 -8.174438,-0.03 -14.394674,0 z" /></svg><script src="anime.js"></script><script>anime({targets: '.path',d: {// 改变d,从一种状态改变到另一种状态value: ["m 41.416254,90 c -0.327378,-7.4702 0.20833,-32.7284 0,-39.901 -5.386902,-0.2083 -4.521603,0.3274 -9.848987,0 0.20833,-5.50595 0.36436,-7.66666 0.126269,-13.32142 4.646472,0.0181 3.439989,-0.009 9.848987,-0.1894 0.09586,-3.7736 0.133082,-3.0791 0.126269,-7.38674 0.18259,-3.73943 -0.486609,-10.54308 4.293149,-14.96288 4.779758,-4.4198 13.606811,-3.64808 22.223356,-3.53554 -0.04417,5.73754 -0.03936,9.37986 0,12.87945 -5.049924,0.46388 -7.309188,-0.33689 -10.85914,1.26269 -1.403378,3.17794 -1.569601,4.80531 -1.262691,11.93242 3.147964,-0.13336 8.201788,-0.1378 12.626907,0 -0.995158,6.00899 -0.948285,7.62376 -1.767767,13.06882 -3.676625,0.088 -5.605721,-0.1488 -11.111678,0 -0.148814,6.756 0.357147,33.0107 0,40.1536 -6.428576,0.1786 -8.174438,-0.03 -14.394674,0 z","m 10.44335,90 c 11.073313,0.3952 19.483106,-1.8358 23.901837,-7.1603 -7.9736,-1.4292 -11.832311,-4.1933 -15.078321,-11.0837 3.459698,0.8219 5.795894,0.6358 7.606781,-0.607 -7.19593,-1.719 -12.734543,-6.7971 -13.741664,-15.836 2.766355,1.55307 5.466848,2.66623 7.828682,2.0203 -4.336544,-2.92911 -9.838998,-10.47636 -5.555839,-22.47589 8.400675,11.87052 23.824269,17.67568 33.840111,17.67767 -0.936406,-9.74688 5.88057,-19.46521 15.302849,-19.97853 8.13118,-0.50719 10.57457,4.01944 12.476346,4.82624 3.644547,0.13419 7.393301,-1.74401 10.354063,-3.53553 -1.380842,4.47157 -5.06769,5.62903 -6.313453,8.58629 5.42317,0.41513 5.891376,-1.53111 8.333758,-2.0203 -2.071414,3.75017 -5.393863,5.00034 -7.323606,8.08122 -1.633654,16.12573 -5.16049,27.57123 -14.647212,36.36553 -13.825764,11.3764 -34.755458,17.369 -56.984332,5.14 z"],// 动画持续时间duration: 2000,// 动画缓动效果easing: 'easeInOutQuart'},// 填充的颜色fill: {value: ['#3b5998', '#4099ff'],duration: 2000,easing: 'easeInOutQuart'},// stroke是线的颜色stroke: {value: ['#3b5998', '#4099ff'],duration: 2000,easing: 'easeInOutQuart'},})</script> </body></html>
我们创建new-anime.js文件,来实现animejs中实现svg的部分,细节详见代码的备注部分:
function anime(params) {// instance:相关属性仍然挂载在一个对象下,代表当前动画// raf ;代表当前标识var instance = {},raf;instance.duration = 0;// 1. 将动画需要改变的属性存储起来// properties中存储d、fill、stroke这三个属性instance.properties = [];instance.animations = [];for (var key in params) {if (key !== 'targets') {instance.properties.push(key)} else {instance[key] = params[key];}}// 2. 将属性和目标元素匹配,生成动画数据instance.properties.forEach(function (item) {// animation:每拿到一个属性,就会创建一个动画数据,用animation来接收var animation = {};animation.property = item;// from:是d、fill、stroke中value的第一个值 、fill中value针对颜色我们还要进行转换// 如果是颜色值,我们还需要对颜色进行转换成rgb,然后再存储起来// to:是d、fill、stroke中value的第二个值// isHex:判断是否为颜色值// hexToRgba:转换为rgb的格式animation.from = isHex(params[item].value[0]) ? hexToRgba(params[item].value[0]) : params[item].value[0];animation.to = isHex(params[item].value[1]) ? hexToRgba(params[item].value[1]) : params[item].value[1];// 将每个值单独取出来,进行处理.// 比如将rgb中的r取出来r跟r计算 / g跟g计算...animation.from = valueNormalize(animation.from);animation.to = valueNormalize(animation.to);// 存储属性animation.duration = params[item].duration;animation.easing = params[item].easing;// 将持续时间取最大值赋值给instance.duration = instance.duration > animation.duration ? instance.duration : animation.duration;instance.animations.push(animation);})// 处理每一帧instance.tick = function (t) {if (t > instance.duration) {return;}instance.animations.forEach(function (animation) {if (t <= animation.duration) {var value = [];// animation.from.numbers:这里就是把属性的r拆开了,把d中的数字都拆开了animation.from.numbers.forEach(function (item, index) {// 计算改变量:颜色值是不允许出现小数的,但是d的点的坐标是可以的,所以要做区分if (isRgb(animation.from.original)) {// easeInQuart:运动的改变量// 将其转为整数,颜色的值不可以带小数,然后存储到value中value.push(parseInt(easeInQuart(t,animation.from.numbers[index],animation.to.numbers[index] - animation.from.numbers[index],animation.duration)));} else {value.push(easeInQuart(t,animation.from.numbers[index],animation.to.numbers[index] - animation.from.numbers[index],animation.duration));}})}var strings = animation.from.strings;var stringsLength = strings.length;var progress = strings[0];for (var s = 0; s < stringsLength; s++) {var b = strings[s + 1];var n$1 = value[s];if (!isNaN(n$1)) {if (!b) {progress += n$1 + ' ';} else {progress += n$1 + b;}}}// 设置属性// d是作为path的属性的// fill和stock是style下的if (isRgb(progress)) {instance.targets.style[animation.property] = progress;} else {instance.targets.setAttribute([animation.property], progress);}})}// 动画引擎:if(!raf){play();}function play () {raf = requestAnimationFrame(step);}// 处理每一帧function step(t) {instance.tick(t);if(t > instance.duration){return;}play()}}// 匀速运动的改变:(当前的时间t / 当前的持续时间) * (from - to的时间差)
// 但是由于 easing: 'easeInOutQuart',这是一个缓动的算法,我们使用前人总结的如下算法来计算运动的改变:
// t:当前时间、b:起始值、c:改变量(也就是终止值和起始值的差)、d:总的持续时间
function easeInQuart (t, b, c, d) {return c * (t /= d) * t * t * t + b;
}
// hexToRgba:对颜色进行rgb的转换
function hexToRgba(hexValue) {var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;var hex = hexValue.replace(rgx, function (m, r, g, b) { return r + r + g + g + b + b; });var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);var r = parseInt(rgb[1], 16);var g = parseInt(rgb[2], 16);var b = parseInt(rgb[3], 16);return ("rgba(" + r + "," + g + "," + b + ",1)");
}
// isHex:判断是否为颜色值
function isHex(a) { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a); }
// isRgb:判断是否为rgb
function isRgb(a) { return /^rgb/.test(a); }
// 把每个值单独取出来
function valueNormalize(val) {var rgx = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g; // handles exponents notationreturn {original: val,numbers: val.match(rgx) ? val.match(rgx).map(Number) : [0],// 用来存单位strings: val.length ? val.split(rgx) : []}
}
创建完成,这时我们同样通过script标签引入我们自己实现的包
<script src="new-anime.js"></script>
由于没有进行targets的处理,这里需要使用原生js方法来获取目标元素,除了这一点与animejs不同,其余效果我们可以看到完全相同,并且只书写了一百多行代码,性能得到了提升:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><svg class="social" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path class="path"style="fill:#3b5998;fill-rule:evenodd;stroke:#3b5998;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"d="m 41.416254,90 c -0.327378,-7.4702 0.20833,-32.7284 0,-39.901 -5.386902,-0.2083 -4.521603,0.3274 -9.848987,0 0.20833,-5.50595 0.36436,-7.66666 0.126269,-13.32142 4.646472,0.0181 3.439989,-0.009 9.848987,-0.1894 0.09586,-3.7736 0.133082,-3.0791 0.126269,-7.38674 0.18259,-3.73943 -0.486609,-10.54308 4.293149,-14.96288 4.779758,-4.4198 13.606811,-3.64808 22.223356,-3.53554 -0.04417,5.73754 -0.03936,9.37986 0,12.87945 -5.049924,0.46388 -7.309188,-0.33689 -10.85914,1.26269 -1.403378,3.17794 -1.569601,4.80531 -1.262691,11.93242 3.147964,-0.13336 8.201788,-0.1378 12.626907,0 -0.995158,6.00899 -0.948285,7.62376 -1.767767,13.06882 -3.676625,0.088 -5.605721,-0.1488 -11.111678,0 -0.148814,6.756 0.357147,33.0107 0,40.1536 -6.428576,0.1786 -8.174438,-0.03 -14.394674,0 z" /></svg><script src="new-anime.js"></script><script>anime({targets: document.querySelector('path'),d: {value: ["m 41.416254,90 c -0.327378,-7.4702 0.20833,-32.7284 0,-39.901 -5.386902,-0.2083 -4.521603,0.3274 -9.848987,0 0.20833,-5.50595 0.36436,-7.66666 0.126269,-13.32142 4.646472,0.0181 3.439989,-0.009 9.848987,-0.1894 0.09586,-3.7736 0.133082,-3.0791 0.126269,-7.38674 0.18259,-3.73943 -0.486609,-10.54308 4.293149,-14.96288 4.779758,-4.4198 13.606811,-3.64808 22.223356,-3.53554 -0.04417,5.73754 -0.03936,9.37986 0,12.87945 -5.049924,0.46388 -7.309188,-0.33689 -10.85914,1.26269 -1.403378,3.17794 -1.569601,4.80531 -1.262691,11.93242 3.147964,-0.13336 8.201788,-0.1378 12.626907,0 -0.995158,6.00899 -0.948285,7.62376 -1.767767,13.06882 -3.676625,0.088 -5.605721,-0.1488 -11.111678,0 -0.148814,6.756 0.357147,33.0107 0,40.1536 -6.428576,0.1786 -8.174438,-0.03 -14.394674,0 z","m 10.44335,90 c 11.073313,0.3952 19.483106,-1.8358 23.901837,-7.1603 -7.9736,-1.4292 -11.832311,-4.1933 -15.078321,-11.0837 3.459698,0.8219 5.795894,0.6358 7.606781,-0.607 -7.19593,-1.719 -12.734543,-6.7971 -13.741664,-15.836 2.766355,1.55307 5.466848,2.66623 7.828682,2.0203 -4.336544,-2.92911 -9.838998,-10.47636 -5.555839,-22.47589 8.400675,11.87052 23.824269,17.67568 33.840111,17.67767 -0.936406,-9.74688 5.88057,-19.46521 15.302849,-19.97853 8.13118,-0.50719 10.57457,4.01944 12.476346,4.82624 3.644547,0.13419 7.393301,-1.74401 10.354063,-3.53553 -1.380842,4.47157 -5.06769,5.62903 -6.313453,8.58629 5.42317,0.41513 5.891376,-1.53111 8.333758,-2.0203 -2.071414,3.75017 -5.393863,5.00034 -7.323606,8.08122 -1.633654,16.12573 -5.16049,27.57123 -14.647212,36.36553 -13.825764,11.3764 -34.755458,17.369 -56.984332,5.14 z"],duration: 2000,easing: 'easeInOutQuart'},fill: {value: ['#3b5998', '#4099ff'],duration: 2000,easing: 'easeInOutQuart'},stroke: {value: ['#3b5998', '#4099ff'],duration: 2000,easing: 'easeInOutQuart'},})</script>
</body></html>
这里我再进行一下总结,实现svg的内容主要分为一下4个步骤:
1. 处理参数属性
2. 将参数属性处理成动画数据
3. 设置帧
4. 动画引擎
【AnimeJs】——仿Animejs徒手实现SVG动画相关推荐
- android 载入svg动画,Android 加载SVG动画
Android 加载SVG动画 SVG 可以说是目前比较流行的图片格式,使用领域也十分广泛,例如:web 前端页面,Android ios 等移动应用.都可以使用 SVG 的图片格式.今天就要和大家谈 ...
- html流程svg动画,12款基于SVG的HTML5应用和动画
本文作者html5tricks,转载请注明出处 SVG是HTML的扩展标记语言,利用SVG可以做非常多的矢量动画,结合 1.HTML5 SVG 3D蝴蝶飞舞动画 逼真超酷 这次我们要分享的这款HTML ...
- php仿苹果,关于8个超炫酷仿苹果应用的HTML5动画的图文详解
苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...
- 8个超酷炫仿苹果应用的HTML5动画
苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...
- ios8.0 html样式,8个超炫酷仿苹果应用的HTML5动画
苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...
- 8个超酷炫的仿苹果应用的HTML5动画
苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...
- 简单的 docker SVG 动画(无聊之作)
最近有点心血来潮,想做一个关于docker的一个中间层,以便更好的实现热部署以及docker容器的周期监控,当然本章不是这个内容,只是因为这个而做的一个小的加载动画. 工具: svgator(现为商业 ...
- svg配合css3动画_带有Adobe Illustrator,HTML和CSS的任何网站的SVG动画
svg配合css3动画 A top trend in web design for 2020 is the increased use of SVG animations on web pages a ...
- svg动画制作_制作第一个SVG动画
svg动画制作 Story of a designer trying to code animations instead of asking a dev to figure it out. 一位设计 ...
最新文章
- scala集合同时支持不可变集合和可变集合
- 07_UI基础_UITableView实战- 支付宝口碑
- 简单介绍蓝牙无线模块和手机进行的车数据交互技巧
- 鸿蒙测试机型微博,华为多款机型开启鸿蒙尝鲜:微博已适配HarmonyOS小尾巴
- Magento 添加后台管理 addColumn
- oracle rollup 排序,oracle分组函数之ROLLUP演示
- java 反解析cron_Java解析Cron表达式
- 迅雷界面引擎Bolt中编译失败的问题
- Android BT种子文件解析
- vivado simulation仿真(38译码器实现)
- 完全免费的Windows代码签名证书(大神勿喷)
- 解决vscode的报错:Java 11 or more recent is required to run the Java extension
- visual studio 提高速度的选项
- Representation Learning 表示学习(简单笔记)
- 语言学及应用语言学类毕业论文文献有哪些?
- 深度学习超分辨率综述阅读笔记(翻译)
- 鸿蒙王者荣耀想要转区吗,王者荣耀开放转区 转区转角色服务要求条件汇总
- 跳跃游戏(Java)
- xdoj 1192: 锘爷考驾照
- 程序员:不要自称为码农
热门文章
- [折腾日记]win10 ,ubuntu双系统安装避坑指南
- 荣耀V40用机技巧有哪些
- 同济:004.三角函数(1.1映射与函数)
- js 获取输入的首字母拼音
- cocos2d-x创建新项目模板
- VS Code 报Windows找不到文件‘chrome‘. 请确定文件名是否正确后,再试一次。八种解决办法
- Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class redacted.BasicEnt
- 别瞎学了,我的MySQL学习之路(超详细超硬核)
- C++中endl的本质是什么
- 【Windows 7中的凭据管理器的功能】