Pfz.AnimationManagement.js

分享于 

17分钟阅读

Web开发

  繁體

查看运行的示例

Cyberminds 57 示例。

CollisionDetection + 爆炸示例示例。

背景

以前我编写了流畅和命令式动画文章,其中我展示了一个能够混合命令和声明动画的动画库。 网网。 现在是时候提供这样一个版本的库,用于面向对象的JavaScript文档。

我为我写了一篇文章,考虑到我喜欢 C#,对我来说,对我来说,我写一篇文章看起来很奇怪。 如果微软决定让Silverlight更支持Silverlight我可能会使用 Silverlight,但考虑到Silverlight不再是 discontinued,我决定使用something的platform,这是我的wife,这是 JavaScript。

动画库的原因?

在开始为 JavaScript编写文章之前,我searched看是否已经为 JavaScript 制作动画库。

在某些地方我已经找到了我们不需要动画库的信息 CSS 已经能够创建动画了。 我发现,即使是 jQuery,也可以编写动画。

CSS 动画的问题在于它们只是声明性的。 没有办法将命令代码作为动画的一部分,以及工作arounds来尝试使代码过于复杂。 还有很多特殊效果仍然是"供应商特定"需要很多不同的方式来支持不同的浏览器来支持不同的浏览器,或者效果将只是失败。 在使用 CSS,我甚至发现了一个小游戏,但是它使用太多的"技巧"来避免的JavaScript代码,因为它不再适合设计器。 但这不是程序员的代码。 所以,在我看来,如果我们想要交互式动画,那么 CSS 是不好的。

关于 jQuery,也许是我的误解,但显然它只有基本效果,所以它远不适合写一个游戏。 我将在这里出现的图书馆已经测试写游戏,即使游戏现在没有完成。"。 大多数代码是 C# 版本的简单端口,这意味着如果要学习单个库,则可以在和 JavaScript 中reutilise的大多数概念。

此外,在基于浏览器的JavaScript 制作动画的优势是,效果可能需要厂商特定的参数,而不是在 CSS中写的动画。

智能执行备份/恢复

从概念上讲,一切都从具有 reset()update() 功能的接口开始。

update() 函数将从上次调用后接收经过的时间,以毫秒为单位。

reset() 函数,它负责将实际动画重置为原始值。

为了有效地运行动画,调用 AnimationManager.add() 函数提供动画对象是足够的。

即使这个原则看起来太简单,它也非常强大,因为它可以用不同的方法来创建交互动画:

AnimationBuilder.
beginParallel().
 beginLoop().
 beginPrematureEndCondition(function () { return _horizontalMovement <= 0; }).
 rangeBySpeed(function () { return _left; }, 700-64, 120, function (value) { _left = value; playerCharacter.style.left = value; }).
 endPrematureEndCondition().
 endLoop().
 beginLoop().
 beginPrematureEndCondition(function () { return _horizontalMovement> = 0; }).
 rangeBySpeed(function () { return _left; }, 0, 120, function (value) { _left = value; playerCharacter.style.left = value; }).
 endPrematureEndCondition().
 endLoop().
 beginLoop().
 beginPrematureEndCondition(function () { return _verticalMovement <= 0; }).
 rangeBySpeed(function () { return _top; }, 500-64, 120, function (value) { _top = value; playerCharacter.style.top = value; }).
 endPrematureEndCondition().
 endLoop().
 beginLoop().
 beginPrematureEndCondition(function () { return _verticalMovement> = 0; }).
 rangeBySpeed(function () { return _top; }, 0, 120, function (value) { _top = value; playerCharacter.style.top = value; }).
 endPrematureEndCondition().
 endLoop().
endParallel();

你可以看到它在这里运行 你可以使用 cursor 键移动船舶。

实际上,我说它是一个"接口",因为每个实现都可以用这些函数来做任何事情。 因此,使本示例工作所发生的事情是:

  • RangeBySpeedAnimation 接收到 to,finalValue,值将在一秒内更改的数量和更新UI的函数。 如果你想让动画在1 毫秒内移动,那么在毫秒后,如果函数被调用,那么这个函数将增加 53。 这将自然补偿可能发生的减速,这比在每个"滴答"上使用固定"定位 +="要好得多;
  • LoopAnimation 是"装饰器"动画,它继续对内部动画进行重定向,但当内部动画结束时,将重新设置它;
  • PrematureEndCondition 是另一个"装饰器"。 但是在这种情况下,当结束条件不是 true 时,它只调用内部动画。 一旦它是 true,它就停止它的内部动画;
  • ParallelAnimation 和SequentialAnimation是"粘附"所有部分的动画。 NAME 说,一个并行地运行动画,另一个作为序列运行。 序列动画的最佳特点是它不关心动画所花的时间。 下一个动画只有在前一个结束时才开始,后面是一秒,后面是 3小时;
  • 正如你可以能想象的,整个"表达式"使用这些动画,但是它是用一个流行的API ( 这就是为什么名字不完全是在表达式中键入的内容) 编写的;
  • 还有其他一些装饰器可以用来加速或者使用内置动画,通过简单的创建和重置功能创建你自己的动画/装饰器。

声明性 API

声明性API只是让事情看起来更具声明性,甚至在正确的地方呈现函数。

例如,你可以随时创建一个 WaitAnimation,但如果将 inside 设置为 ParallelAnimation,则无用。 现在尝试把它放在一个上,它就有意义。

在Fluent中,wait() 函数只存在于 SequentialAnimation ( 使用beginSequence创建( ) 中,而不存在于ParallelAnimation中。

声明式API的功能

声明性API的功能包括:

beginSequence ( )
endSequence ( )
创建序列动画,它是播放其他动画( 内部动画)的动画帽。
beginParallel ( )
endParallel ( )
创建一个并行动画,它是一个并行播放所有内部动画的动画。
添加( animationOrFunction )将已经创建的动画对象或者动画功能添加到实际动画组或者装饰器。
如果函数作为动画给出,就像它是"更新"那样被调用,因为它是自上次调用以来经过的。 这样的函数可以直接处理数据,也可以返回其他动画,从而可以检查某些条件,并有效地返回另一个特定的动画来运行这些动画。
范围( initialValue,finalValue,持续时间,updateFunction )创建一个动画,从初始值到特定持续时间( 以毫秒为单位) 中的final 值。 每次动画"刻度"调用 updateFunction,给出计算值,考虑到 initialValue。finalValue和 duration。
需要注意的是,initialValue。finalValue或者duration可以是实际返回这些值的函数。 如果创建声明式表达式时不存在值,则这里选项很有用。

这里动画显示两个范围以不同的结束值并行运行,但持续时间相同。
rangeBySpeed ( initialValue,finalValue,速度,updateFunction )这与前一个类似,但不是给动画指定一个指定的时间,这是一个值,这个值每秒改变一个。
使用速度代替固定时间是动画交互时的preferrable。 同样,range() 函数,参数 initialValue,finalValue和速度可以是函数,在调用时返回这些值。

这个动画显示两个rangeBySpeed动画以不同的结束值并行运行,但速度相同。
beginRunCondition ( 条件)
endRunCondition ( )
将条件设置为运行单个内部动画( 注意,内部动画可以是并行的ou序列动画,所以你可以间接地播放许多动画)。 动画开始播放后,如果条件改变,它就不重要了,它将继续播放。
beginPrematureEndCondition ( 条件)
endPrematureEndCondition ( )
这里函数将一个条件提前结束内部动画。 在释放键时使玩家角色停止移动是非常有用的。
beginLoop ( )
endLoop ( )
这个装饰器一旦结束就会重新启动它的内部动画。
beginTimeMultiplier ( 因子)
endTimeMultiplier ( )
将给定的动画timelapses的值乘以给定的因子,可以是直接值或者生成这样值的函数。 这有效地使动画运行得更快或者更慢。
beginPauseCondition ( 条件)
endPauseCondition ( )
每次检查时都会检查情况。 如果是 true,则不执行内部动画。 这样可以有效地暂停内部动画,而条件是 true。
beginSegmentedTime ( 间隔,segmentCompleted )
endSegmentedTime ( )
分段动画的内部动画将使用最大间隔更新内部动画,有效地播放内部动画。 例如如果你想应用碰撞检测"每帧",但使用声明性( 时间和时间) 动画,这很有用。
每次段完成( 因此,如果timelapse小于段大小,则不会调用它) 时都会调用可选的segmentCompleted函数,给出适当的时间来应用碰撞检测,例如。
等待( 持续时间)等待给定时间( 毫秒) 通过。 持续时间可以是一个函数,在每次调用时可能返回不同的等待时间。 这里函数仅适用于 inside 序列。
waitCondition ( 条件)等待条件函数返回 true。 就像 wait() 函数一样,它只有 inside 序列。

创建自己的动画段

如上所述,这个库仅基于 update() 和 reset() 函数。 通过使用这 2个函数创建一个新对象,更新接收自上次调用之后的毫秒,可以创建自己的动画段。 NumericRangeAnimation 是最基本的例子,但是你可以创建动画动画或者使用非线性结果,例如。

但是我想解释 NumericRangeAnimation,这样你就可以有一个起点了:

function NumericRangeAnimation(initialValue, finalValue, duration, updateFunction) {
 this._beforeStart = true;
 this.initialValue = initialValue;
 this.finalValue = finalValue;
 this.duration = duration;
 this.updateFunction = updateFunction;
};// This constructor will simply store all the given parameters and set a value// telling that it was not started yet.NumericRangeAnimation.prototype.reset = function () {
 this._beforeStart = true;
}// Well, the reset only says that it was not started yet, so the// update will start it.NumericRangeAnimation.prototype.update = function (elapsed) {
 // as you can see, if the animation was not started yet, it will// be started now.if (this._beforeStart) {
 this._beforeStart = false;
 this._total = 0;
 // the AnimationManager._getValue is to be considered a kind of//"internal method". It is capable of evaluating a function to // get its result or it simply returns the value directly.// evaluating the function only when the animation is starting// is very important for this animation to work properly, as// we don't want a random function (for example) to be evaluated// at every frame.this._initialValue = AnimationManager._getValue(this.initialValue);
 this._finalValue = AnimationManager._getValue(this.finalValue);
 this._duration = AnimationManager._getValue(this.duration);
 }
 // here, if the total time is greator or equal the// duration, we update the animation with the latest value// and return false, telling that the animation ended.this._total += elapsed;
 if (this._total> = this._duration) {
 this.updateFunction(this._finalValue);
 return false;
 }
 // here we do the actual range calculation, call the update function// so the UI element can be updated and we return true, telling// that the animation is not finished yet. var remaining = this._duration - this._total;
 var value = ((this._finalValue * this._total) + (this._initialValue * remaining))/this._duration;
 this.updateFunction(value);
 return true;
};

我希望你能通过我这里的评论理解这个动画 Fragment。 但这是不流畅的API。 to API必须在流畅的API中实现一个新的功能,这将会影响到很多开始/结束调用的结果。 为此,我们使用 AnimationBuilder.registerAnimationBuilderModifier 接收函数以更改所有已经存在的动画生成器类型的Prototype的函数。

例如如果 range() 函数没有注册,我们可以用下面的方法对它的进行 register:

AnimationBuilder.registerAnimationBuilderModifier(function (prototype) {
 prototype.range = function (initialValue, finalValue, duration, updateFunction) {
 returnthis.add(new NumericRangeAnimation(initialValue, finalValue, duration, updateFunction));
 };
});

使用这里范围动画可以使用 inside,AnimationBuilder 已经存在段。

JavaScript和 C# 库

我在 C# 中建立了更好的例子,如果你愿意,可以查看 C# 示例来查看该库具有的潜力。

C# 代码实际上有更多的动画段,它可以在序列( 如果一个动画以下 10毫秒结束,下一次失败带有 15微秒,5毫秒转到下一个动画) 中更正两个段之间的运行时间。 我做了简化的javascript版本,因这里它不会处理这个问题。

但是我认为库非常强大,特别是因为它允许创建没有特定持续时间的交互式动画。 如果你查看 C# 库,需要记住的一些重要事项是:

  • 基于java的JavaScript插件版本使用毫秒作为默认计时,而 C# 一使用秒或者真正的TimeSpan (
  • C# 中的名称使用的大写值与JavaScript中的名称不同;
  • 实际上,版本支持更多参数作为函数。 在 C# 中,仅存在一些支持委托( 是的,在这种意义上,的JavaScript版本更好)的重载;
  • 由于 C# 是带有泛型的类型化语言,所以 C# Range 实际上可以处理整数。双精度。颜色和任何种类的范围,如果你将它的添加到 register。 对于必须支持的每个不同类型,JavaScript 版本需要一个新的函数( 像一个 pointRange )。

动画  
相关文章