TweenMax 源码阅读

news2024/11/16 3:19:34

GSAP 之 TweenMax 源码阅读(一)

一、背景 GreenSock (绿袜子)

GreenSock 是一家做 专业级 JavaScript 动画的公司,主要产品就是其下的 GSAP (GreenSock Animation Platform),配合着 GSPA 开发了很多专业的动画插件。

GSAP (GreenSock Animation Platform)

GSAP 是一个强大的 JavaScript 工具集,可以让开发人员开发出高级动画。构建适用于所有主流浏览器的高性能动画。动画化 CSS、SVG、画布、React、Vue、WebGL、颜色、字符串、运动路径、通用对象……任何 JavaScript 可以触及的东西!

在解决超过 1100 万个站点的实际问题的同时,没有其他工具能够提供如此先进的排序、可靠性和严格控制。GSAP 解决了无数的浏览器不一致问题;你的动画效果很好。GSAP 的核心是一个高速属性操纵器,随着时间的推移以极高的准确性更新值。它比 jQuery 快 20 倍!
简而言之,GSAP 是地球上最强大的高性能 JavaScript 动画库,这可能是谷歌推荐它用于基于 JS 的动画并且每个主要广告网络都将其排除在文件大小计算之外的原因。与指示您如何构建应用程序的单一框架不同,GSAP 完全灵活;洒在任何你想要的地方。
官网地址:https://greensock.com/gsap/

二、GSAP特点(优势)

1、Crazy fast (疯狂快)

性能至关重要,尤其是在处理器速度较慢的移动设备上。丝般流畅的动画是任何值得其重量的图书馆的标志,GSAP 在压力下比旧的“行业标准”高出 1000%+。生涩和抽搐的东西现在是流动的。它是无数优化的结果,以确保您的交互式项目响应迅速、高效且流畅。查看速度测试以进行面对面的比较。

2、Freakishly robust (异常坚固)

为专业人士构建的 JavaScript 动画,GSA​​P 包含的功能使大多数其他引擎看起来像廉价玩具。动画颜色、贝塞尔曲线、CSS 属性、数组等等。构建令人惊叹的滚动触发效果。舍入值、动态平滑 reverse()、使用相对值、自动适应 getter/setter 函数、使用几乎任何缓动方程,并像专业人士一样管理冲突的补间。定义回调、毫不费力地构建序列(即使有重叠补间)、重复/溜溜球等等。使用简单、随意组合、自己解决诸多异常

3、Compatible(兼容性)

HTML、SVG、React、Vue、Angular、jQuery、Canvas、CSS、新浏览器、旧浏览器、移动设备等等——GSAP 与它们相处得很好。使用您最喜欢的工具,而无需跳过无休止的箍,以确保兼容性。GSAP“正常工作”。我们担心兼容性,因此您不需要担心。又一个头痛的问题解决了。

4、Animate anything(动画任何东西)

这是正确的。任何事物。没有可供选择的预定义属性列表。任何对象的任何数字属性都可以设置动画。GSAP 可以处理几乎任何格式的带有嵌套颜色的复杂字符串值。它会自动检测基于函数的值。有大量的实用方法可以解决常见问题。可能性是无止境。

5、Lightweight & expandable(轻巧且可扩展)

模块化、灵活且超高效,其插件架构使核心引擎保持紧凑,同时允许通过可选插件添加几乎任何功能。GSAP 将惊人的能量装入一个小得惊人的封装中。

6、Zero dependencies(零依赖)

GSAP 不是建立在任何第 3 方工具(如 jQuery)之上(尽管它与 jQuery 配合得很好)。这种方法最大限度地减少了加载时间并最大限度地提高了性能。不需要任何其它工具,直接使用

7、Advanced sequencing(高级排序)

不仅限于“一个接一个”的排序;让动画尽可能多地重叠。将时间线嵌套在其他时间线内。插入间隙、回调、标签、交错补间等等。您可以获得对时间的精确控制和前所未有的灵活性,从而用最少的代码创建富有表现力的动画。

8、Dedicated support(专门支持) ??

每个人有时都需要一点帮助。我们支持你。当截止日期迫在眉睫而您无法解决问题时,请跳转到greensock.com/forums以获得与 GSAP 相关的问题的解答。有超过 100,000 个帖子!GreenSock 工具不同于大多数停滞不前或提供零支持的开源项目。有论坛帮你解决问题

三、GSAP 核心插件 TweenMax

GSAP 有很多插件,不过大部分是收费的,例如 DrawSVG , Physics2D , PhysicsProps , ScrambleText , CustomBounce , CustomWiggle,MorphSVG , Inertia 插件, SplitText , MotionPathHelper , GSDevTools , ScrollSmoother 等等 功能都很强大。TweenMax 目前免费开源,这里我们只关注 TweenMax。

TweenMax 是 GreenSock 动画平台的核心,配合其他插件就可以,对css属性、颜色、滤镜效果、颜色值、桢等等做动画。具体效果和使用可以参考中文官网地址:
https://www.tweenmax.com.cn/index.html

1、TweenMax 的使用

TweenMax 使用起来很简单

使用参考:https://www.tweenmax.com.cn/api/tweenmax/TweenMax()

效果展示:https://www.tweenmax.com.cn/demo/

2、TweenMax 原理解析

结构组成

以下代码部分都为简化的代码

1、EventDispatche 事件调度中心(分发器)

类似观察者模式的一个组件,负责收集依赖和分发事件;

var EventDispatcher = _class("events.EventDispatcher", function (target) { ... })
// 事件监听器
p.addEventListener = function (type, callback, scope, useParam, priority) { ... }
// 事件删除
p.removeEventListener = function (type, callback) {}
// 事件触发器
p.dispatchEvent = function (type) { ... }
2、Ticker 时间启动器

也可叫做动画驱动器,播放时一直自循环,实时校准当前时间,并且向外分发当前时间 time;
Ticker 根据浏览器渲染频率 16.667ms 驱动 SimpleTimeline(根时间轴),主要使用 requestAnimationFrame 方法,低端浏览器时,使用 setTimeout 来兼容;

_class("Ticker", function (fps, useRAF) {
  this.funName = "Ticker";
  ...
  _tick = function (manual) {
    _self.time = (_lastUpdate - _startTime) / 1000;
     if (!_fps || overlap > 0 || manual === true) {
       _self.frame++;
       dispatch = true;
     }
     _id = _req(_tick);
     if (dispatch) {
       _self.dispatchEvent(_tickWord);
     }
   };
   _self.sleep = function () {...};
   _self.wake = function (seamless) {...};
   ...
}
3、Animation 动画播放器

主要负责将动画,挂载到根时间轴,同时记录该动画的各项参数;

4、TweenMax/TweenLite 播放单元

负责播放动画,是功能最多的组件,主要功能有:

  • 实例动画,记录动画状态;
  • 提供插件API,处理用户传入参数(链表化参数);
  • 渲染动画的每一帧播放,并判断当前阶段对应执行该阶段的回调函数;
  • 播放速度曲线控制,需要借助另一个插件 Ease,默认只有几种简单速度曲线;
var TweenLite = _class( "TweenLite", function (target, duration, vars) { ... })
p = TweenLite.prototype = new Animation();
p.constructor = TweenLite;
p._init = function() { ...// 第一次渲染时处理参数 }
p._initProps = function(target, propLookup, siblings, overwrittenProps, index) { ... }
p.render = function(time, suppressEvents, force) {
	...
	// 动画播放程度渲染
	self._totalTime = self._time = time;
	self.ratio = self._ease.getRatio(time / duration);
	pt = self._firstPT;
	while (pt) {
		if (pt.f) {
			pt.t[pt.p](pt.c * self.ratio + pt.s);
		} else {
			pt.t[pt.p] = pt.c * self.ratio + pt.s;
		}
		pt = pt._next;
	}
	// 回调函数执行
	if (callback){..}
}
p._kill = function(vars, target, overwritingTween) { ... }
...
// TweenLite 静态方法
TweenLite.to = function(target, duration, vars) { ... }
TweenLite.from = function(target, duration, vars) { ... };
TweenLite.fromTo = function(target, duration, fromVars, toVars) { ... };
TweenLite.delayedCall = function(delay, callback, params, scope, useFrames) { ... };
TweenLite.set = function(target, vars) { ... };
TweenLite.getTweensOf = function(target, onlyActive) { ... };
...
5、 SimpleTimeline/ TimelineLite 根时间轴线与普通时间轴线

时间轴主要维护一个动画队列,负责挂载动画,由 Ticker 驱动收到调用时负责循环执行时间轴上挂载的所有动画。 这里两者有区别:
SimpleTimeline 会执行所有动画;(这里是页面上的所有动画)
TimelineLite 而会按照当前时间执行对应时间区间内的动画;
并且,TimelineLite 最终也会作为一个子集挂载到 SimpleTimeline 上;

var SimpleTimeline = _class("core.SimpleTimeline", function (vars) {
    Animation.call(this, 0, vars)
  });
  p = SimpleTimeline.prototype = new Animation();
  p.constructor = SimpleTimeline;
  ...
  p.add = p.insert = function (child, position, align, stagger) {
    ...
    var prevTween, st;
    prevTween = this._last;
    if (prevTween) {
      child._next = prevTween._next;
      prevTween._next = child;
    } else {
      child._next = this._first;
      this._first = child;
    }
    ...
    return this;
  };
  p._remove = function (tween, skipDisable) { ... };
  p.render = function (time, suppressEvents, force) {
 		...
    var tween = this._first, next;
    while (tween) {
      next = tween._next; // 先在此处记录它,因为渲染后值可能会更改
      if (
        tween._active ||
        (time >= tween._startTime && !tween._paused && !tween._gc)
      ) {
        if (!tween._reversed) {
          tween.render(
            (time - tween._startTime) * tween._timeScale,
            suppressEvents,
            force
          );
        } else {
          tween.render(
            (!tween._dirty ? tween._totalDuration : tween.totalDuration()) -
              (time - tween._startTime) * tween._timeScale,
            suppressEvents,
            force
          );
        }
      }
      tween = next;
    }
  };
  p.rawTime = function () { ... };

结构图:
结构图片

TweenMax插件运行时

  1. 页面打开开始执行js 初始化;
  2. 创建 Ticker 继承 Event(创建Ticker后会启动,为了兼容各种情况的),一段时间后没有动画挂载会自动停止;
  3. 创建 SimpleTimeline 继承 Animation ,并将其渲染函数,注册到 Ticker 的观察者上,供 Ticker 驱动;
  4. 初始化各类参数,包括初始时间,状态等,之后加载开发者代码;
  5. 执行开发者写入代码;例如:
let tween = TweenLite.to(demo, 2 ,{
	red:255,
	score:5100,
	ease: Power1.easeIn,
	onUpdate: showScore
});
  1. 创建 TweenLite 实例继承 Animation 类,注册动画ID。这里在继承 Animation 类的时候,将自己挂载到 SimpleTimeline 的动画链表上,也是动画队列上;
  2. 此时进入页面不久,Ticker 还在启动状态中,6过程完成后,如果没有暂停参数,就会发现 SimpleTimeline 队列中有动画,则开始执行,SimpleTimeline 中的动画;
  3. SimpleTimeline 调入,TweenLite 中的render函数,渲染此时的动画,开始正式执行;
  4. 执行动画,第一次进入 TweenLite 中的render函数中时,会初始化动画状态,链表化初始数值,记录初始状态等等,之后会循环执行,参数数值的变化,并判断当前执行的阶段对应执行阶段回调函数;
  5. 动画的停止,动画本身执行完成时,会一直维持结束状态,而时间启动器 Ticker 此时还在继续执行;
  6. 时间轴本身有自检机制,每120桢检查一次是否还有动画在执行,没有的话,就会停止 Ticker ,减少CPU消耗,到此整个动画执行结束。

执行流程图:待补充

3、多个动画的添加,TimelineLite

1、如何添加动画的?

时间轴有个链表队列,每次添加新动画都是使用 add 方法默认往最后添加;

2、如何实现时间的提前和延后的?position

每次添加新动画时,都会记录所有动画完成的时间 _duration,下次有新动画添加时,根据参数加减时间,计算出这次动画的开始时间,并添加到时间轴;

3、时间轴的特别处理

时间轴在已经开始渲染的情况下,也可以继续添加或者删除动画,会自动矫正其位置,到了时间自动播放;
dome展示

4、使用灵活

兼容多种使用传参方式 TimelineLite
在这里插入图片描述
https://www.tweenmax.com.cn/api/timelinemax/

时间轴图:同上处

四、版本变化 3.0

核心的动画实现原理没有变;主要变化了编写方式和使用方面:

  1. 对代码编写方式,进行了升级,使用了现成工程化,大量使用了ES6语法,尤其再类和继承方便的编写,代码量减少了很多;
  2. 组件间的功能进行了一些调整,分出了 TweenLite 的部分功到 Animation 组件使承担更多功能,取消了 EventDispatche 组件之前只单纯添加了一个 Ticker 事件;
  3. 合并了TweenMax、TweenLite、TimelineLite 和 TimelineMax四个模块,更新了API的调用方式,使用起来更加简单便捷。

具体变化可参考:https://greensock.com/3-release-notes

五、GSAP 支持的一些优秀的案例网址展示

网址:https://greensock.com/showcase/

六、一些可以借鉴的动画效果

1、哈尔的移动城堡 https://www.tweenmax.com.cn/cool/howls/
2、弹性进度条 https://www.tweenmax.com.cn/cool/elastic-progress/
3、绿植 https://www.tweenmax.com.cn/cool/drop-tree/

参考网址: https://greensock.com/
https://www.tweenmax.com.cn/index.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/509957.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端架构师-week5-egg.js+云Mongodb快速入门

目录 下载项目模版功能实现流程分析egg.js简介 egg.js 官网 初始化 云 mongodb 云 mongodb 开通 本地 mongodb 安装 mongodb 使用方法 通过 egg.js 框架添加新的API 云 mongodb 开通 本地 mongodb 调试技巧讲解 egg.js 接入 mongodb 方法 云 mongodb 如何连接公网…

mysql深分页

第一种:主键自增id情况: 未改: select * from wx_product_category_info where category_name_cn#{categoryNameCn} and category_type#{categoryType} order by id asclimit #{pageNum}, #{pageSize};在普通的limit条件下,如果…

如何通过appuploader把ipa文件上传到App Store教程步骤

​ iOS APP上架App Store其中一个步骤就是要把ipa文件上传到App Store!​ 下面进行步骤介绍!​ 利用Appuploader这个软件,可以在Windows、Linux或Mac系统中申请ios和上传IPA到App Store Connect。​ 非常的方便,没有Mac也可以…

回炉重造十三----Docker的运用

1、Docker和虚拟机的区别 两者的区别 虚拟化环境下每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。 容器之间可以共享操作系统,比起 VM 被认为是更轻量级.且与 VM 类似,每个容器都具有自己的文件系统、CPU…

42电机插座接线可以用PH2.0冷压端子

文章目录 42电机插座接线可以用PH2.0冷压端子概述笔记备注END 42电机插座接线可以用PH2.0冷压端子 概述 设备上的42电机在我不断调整电机安装位置时, 接线从插孔中折断了. 问厂家, 他们的线也是定制的. 另外, 他是销售, 不清楚具体插座的型号和插座要用的冷压端子是哪种. 因为…

Java 关键字之:package与import

一、package 关键字 为了更好的实现项目中类的管理,提供包的概念使用package声明类或者接口所属的包,声明在源文件的首行包,属于标识符,遵循标识符的命名规则、规范(xxxyyyzzz)、"见名知意"每“.”一次,就代…

windows 下安装Docker (WSL2)

测试环境: VMware Workstation 17 WinServer2022 docker 4.19 python3.8 第一步:环境准备: 1.开启虚拟化 2. 开启WSL、容器功能 重启服务器 第二步: 安装docker 桌面版:Get Docker | Docker Documentation 此时启动会…

Django框架之错误视图和HTTP方法装饰器

本篇主要记录如何定义视图,错误视图有哪些并如何实现自定义, HTTP方法装饰器定义及实现,还有csrf中间件设置位置及关闭。 定义视图 一般在views.py文件下定义 视图参数: 错误视图 400视图 当出现SuspiciousOperation异常并且代…

Linux Kernel内核整体架构(图文详解)

1,前言 本文是“Linux内核分析”系列文章的第一篇,会以内核的核心功能为出发点,描述Linux内核的整体架构,以及架构之下主要的软件子系统。之后,会介绍Linux内核源文件的目录结构,并和各个软件子系统对应。…

WPF 从0开始写笔记,全属性功能深度剖析 20230510

文章目录 FontFamilyFontWeightResizeModeAllowsTransparencyMarginCornerRadiusBorder.effectBlurRadiusdirectionVerticalAlignmentTargetTypeControlTemplateDataTemplate 和ControlTemplate的区别StrokePath控件Border FontFamily 在WPF中,FontFamily属性用于指…

5月第1周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!

飞瓜轻数发布2023年5月1日-5月7日飞瓜数据UP主排行榜(B站平台),通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况,为用户提供B站号综合价值的数据参考,根据UP主成长情况用户能够快速找到运营能力强的B站…

【C++】类型转换-static_cast、reinterpret_cast、const_cast、dynamic_cast

文章目录 1. C语言中的类型转换2. 为什么C需要四种类型转换3. C强制类型转换static_castreinterpret_castconst_castdynamic_cast 4.explicit5.RTTI6.考点 1. C语言中的类型转换 在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回…

网易云信 RTC 音频问题排查的挑战与实践

背景与挑战 实时通信(Real-Time Communication,RTC)音频技术是指将音频流实时传输到远程用户的技术,满足线上实时交互的诉求,广泛应用于在线教育、视频会议、直播、泛娱乐社交、金融、医疗、政企等场景。在 RTC PaaS…

组件通信的几种方式

组件通信的几种方式 父组件向子组件传值 在父组件中用自定义组件进行传值,自定义属性写到父组件调用子组件的那个标签中。在子组件中用props进行接收,props写到子组件中与data同级,props是一个数组,内容就是自定义属性的名字。 …

SD nand 与 SD卡的SPI模式驱动

文章目录 SD nand 与 SD卡的SPI模式驱动 1. 概述 2. SPI接口模式与SD接口模式区别 2.1 接口模式区别 2.2 硬件引脚 2.3 注意事项 3. SD接口协议 3.1 命令 3.1.1 命令格式 3.1.2 命令类型 3.2 响应 3.2.1 响应格式 4. SD nand(SD卡)结构描述…

内网渗透之域环境信息搜集

1.查看是否为域环境 net config workstation下面命令能否执行成功和computer brower服务是否开启有关 net view /domain2.查询域内的用户和组 查询域内的所有用户 net user /domain查询域内的所有用户(需要在域控上敲) dsquery user查询域内的某个用户 net user dbadmin /d…

代码随想录算法训练营day36 | 435. 无重叠区间,763.划分字母区间,56. 合并区间

代码随想录算法训练营day36 | 435. 无重叠区间,763.划分字母区间,56. 合并区间 435. 无重叠区间763.划分字母区间56. 合并区间总结 435. 无重叠区间 教程视频:https://www.bilibili.com/video/BV1A14y1c7E1/?spm_id_from333.788&vd_sou…

【Linux】安装node-v16.17.0-linux

【Linux】安装node-v16.17.0-linux 1 下载node-v16.17.0-linux-x64.tar.xz 下载地址:https://nodejs.org/zh-cn 2 解压文件 cd 到node-v16.17.0-linux-x64.tar.xz所在的路径 xz -d node-v16.17.0-linux-x64.tar.xz tar -xvf node-v16.17.0-linux-x64.tar 3 软…

vue2 框架运行原理剖析系列(一)之 new Vue()实例化过程到底做了什么!!!

一、vue 基础用法 1.1 引入vue 1.2 使用vue语法编写ui 1.3 实现数据绑定 示例代码如下 <div id"app">{{ message }} </div> <script> var app new Vue({el: #app,data: {message: Hello Vue!} }) </script>1.4 代码效果&#xff1a;使用浏…

4114 Flipping Game

4114 Flipping Game PTA | 程序设计类实验辅助教学平台 思路&#xff1a;我们定义f[i][j]表示当前已经进行了i轮&#xff0c;并且当前的两个串的不同的数的个数是j&#xff0c;就接下来我们考虑状态转移&#xff0c;首先是假设我们在不同的中挑选了x个进行反转&#xff0c;则需…