我们一般会引入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动画相关推荐

  1. android 载入svg动画,Android 加载SVG动画

    Android 加载SVG动画 SVG 可以说是目前比较流行的图片格式,使用领域也十分广泛,例如:web 前端页面,Android ios 等移动应用.都可以使用 SVG 的图片格式.今天就要和大家谈 ...

  2. html流程svg动画,12款基于SVG的HTML5应用和动画

    本文作者html5tricks,转载请注明出处 SVG是HTML的扩展标记语言,利用SVG可以做非常多的矢量动画,结合 1.HTML5 SVG 3D蝴蝶飞舞动画 逼真超酷 这次我们要分享的这款HTML ...

  3. php仿苹果,关于8个超炫酷仿苹果应用的HTML5动画的图文详解

    苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...

  4. 8个超酷炫仿苹果应用的HTML5动画

    苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...

  5. ios8.0 html样式,8个超炫酷仿苹果应用的HTML5动画

    苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...

  6. 8个超酷炫的仿苹果应用的HTML5动画

    苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...

  7. 简单的 docker SVG 动画(无聊之作)

    最近有点心血来潮,想做一个关于docker的一个中间层,以便更好的实现热部署以及docker容器的周期监控,当然本章不是这个内容,只是因为这个而做的一个小的加载动画. 工具: svgator(现为商业 ...

  8. 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 ...

  9. svg动画制作_制作第一个SVG动画

    svg动画制作 Story of a designer trying to code animations instead of asking a dev to figure it out. 一位设计 ...

最新文章

  1. scala集合同时支持不可变集合和可变集合
  2. 07_UI基础_UITableView实战- 支付宝口碑
  3. 简单介绍蓝牙无线模块和手机进行的车数据交互技巧
  4. 鸿蒙测试机型微博,华为多款机型开启鸿蒙尝鲜:微博已适配HarmonyOS小尾巴
  5. Magento 添加后台管理 addColumn
  6. oracle rollup 排序,oracle分组函数之ROLLUP演示
  7. java 反解析cron_Java解析Cron表达式
  8. 迅雷界面引擎Bolt中编译失败的问题
  9. Android BT种子文件解析
  10. vivado simulation仿真(38译码器实现)
  11. 完全免费的Windows代码签名证书(大神勿喷)
  12. 解决vscode的报错:Java 11 or more recent is required to run the Java extension
  13. visual studio 提高速度的选项
  14. Representation Learning 表示学习(简单笔记)
  15. 语言学及应用语言学类毕业论文文献有哪些?
  16. 深度学习超分辨率综述阅读笔记(翻译)
  17. 鸿蒙王者荣耀想要转区吗,王者荣耀开放转区 转区转角色服务要求条件汇总
  18. 跳跃游戏(Java)
  19. xdoj 1192: 锘爷考驾照
  20. 程序员:不要自称为码农

热门文章

  1. [折腾日记]win10 ,ubuntu双系统安装避坑指南
  2. 荣耀V40用机技巧有哪些
  3. 同济:004.三角函数(1.1映射与函数)
  4. js 获取输入的首字母拼音
  5. cocos2d-x创建新项目模板
  6. VS Code 报Windows找不到文件‘chrome‘. 请确定文件名是否正确后,再试一次。八种解决办法
  7. Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class redacted.BasicEnt
  8. 别瞎学了,我的MySQL学习之路(超详细超硬核)
  9. C++中endl的本质是什么
  10. 【Windows 7中的凭据管理器的功能】