This function is a cool one. It lets you animate *anything*. You just specify a
target fps and run an arbitrary function and it’ll automatically be spaced to
execute at the target speed:
The following will increment a value once every 50ms (1000/20fps) and run
exactly 30 times.
var value:Number = 0;
function increment(val:Number):void{
value+=val;
}
var animated:Function = animateFunction(increment,20);
var savedValue:Number;
for(i=0;i<30;i++){
animated(1);
}
Have fun! B-)
Harbs
> On Jan 5, 2022, at 9:31 AM, [email protected] wrote:
>
> This is an automated email from the ASF dual-hosted git repository.
>
> harbs pushed a commit to branch develop
> in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
>
>
> The following commit(s) were added to refs/heads/develop by this push:
> new dd1c6e4 Added animateFunction
> dd1c6e4 is described below
>
> commit dd1c6e4cd7b082207a39efbf71de31adbb6de0d9
> Author: Harbs <[email protected]>
> AuthorDate: Wed Jan 5 09:31:10 2022 +0200
>
> Added animateFunction
> ---
> .../projects/Core/src/main/royale/CoreClasses.as | 1 +
> .../royale/utils/functional/animateFunction.as | 130 +++++++++++++++++++++
> .../src/test/royale/flexUnitTests/CoreTester.as | 2 +-
> .../test/royale/flexUnitTests/FunctionalTests.as | 34 ++++++
> 4 files changed, 166 insertions(+), 1 deletion(-)
>
> diff --git a/frameworks/projects/Core/src/main/royale/CoreClasses.as
> b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> index 50c3c71..48189b5 100644
> --- a/frameworks/projects/Core/src/main/royale/CoreClasses.as
> +++ b/frameworks/projects/Core/src/main/royale/CoreClasses.as
> @@ -382,6 +382,7 @@ internal class CoreClasses
> import org.apache.royale.utils.functional.debounceLong; debounceLong;
> import org.apache.royale.utils.functional.debounceShort; debounceShort;
> import org.apache.royale.utils.functional.throttle; throttle;
> + import org.apache.royale.utils.functional.animateFunction;
> animateFunction;
>
> import org.apache.royale.core.TextLineMetrics; TextLineMetrics;
> import org.apache.royale.utils.ClassSelectorList; ClassSelectorList;
> diff --git
> a/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/functional/animateFunction.as
>
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/functional/animateFunction.as
> new file mode 100644
> index 0000000..32b9fbf
> --- /dev/null
> +++
> b/frameworks/projects/Core/src/main/royale/org/apache/royale/utils/functional/animateFunction.as
> @@ -0,0 +1,130 @@
> +////////////////////////////////////////////////////////////////////////////////
> +//
> +// Licensed to the Apache Software Foundation (ASF) under one or more
> +// contributor license agreements. See the NOTICE file distributed with
> +// this work for additional information regarding copyright ownership.
> +// The ASF licenses this file to You under the Apache License, Version 2.0
> +// (the "License"); you may not use this file except in compliance with
> +// the License. You may obtain a copy of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +// See the License for the specific language governing permissions and
> +// limitations under the License.
> +//
> +////////////////////////////////////////////////////////////////////////////////
> +package org.apache.royale.utils.functional
> +{
> + COMPILE::SWF{
> + import flash.utils.setTimeout;
> + import flash.utils.clearTimeout;
> + }
> + /**
> + * Returns a debounced function to run after a delay.
> + * The first invocation of the function will be run after its delay.
> + * Any invocations between the first invocation and the delay will be
> ignored.
> + *
> + * @royalesuppressexport
> + * @langversion 3.0
> + * @productversion Royale 0.9.9
> + *
> + */
> + public function animateFunction(method:Function, fps:Number):Function
> + {
> + COMPILE::SWF
> + {
> + var limit:Number = 1000/fps;
> + var timeStamp:Number = 0;
> + var timeoutRef:*;
> + var invocations:Array = [];
> + return function(...args):void
> + {
> + if(timeoutRef){
> + clearTimeout(timeoutRef);
> + timeoutRef = null;
> + }
> + invocations.push(args);
> + var currentTime:Number = new Date().getTime();
> + var timeDiff:Number = currentTime - timeStamp;
> + if(timeDiff >= limit)
> + {
> + if(timeStamp == 0)
> + timeStamp = currentTime;
> + else
> + timeStamp += limit;
> + method.apply(null,invocations.shift());
> + }
> + if(invocations.length && timeoutRef == null)
> + {
> + // currentTime = new Date().getTime();
> + timeDiff = currentTime - timeStamp +
> limit;
> + var nextInterval:Number =
> Math.max(timeDiff,0);
> + timeoutRef = setTimeout(callback,
> nextInterval);
> + }
> +
> + function callback():void
> + {
> + timeoutRef = null;
> +
> + if(!invocations.length)
> + return;
> +
> + var currentArgs:Array =
> invocations.shift();
> + method.apply(null,currentArgs);
> + timeStamp += limit;
> + var timeDiff:Number = new
> Date().getTime() - timeStamp + limit;
> + while(timeDiff < 0)
> + {
> + // catch up on the missing
> frames
> +
> method.apply(null,invocations.shift());
> + if(invocations.length == 0)
> + {
> + return;
> + }
> + timeDiff+=limit;
> + }
> + if(invocations.length)
> + {
> + timeoutRef =
> setTimeout(callback, timeDiff);
> + }
> + }
> + }
> +
> + }
> +
> + COMPILE::JS
> + {
> + var limit:Number = 1000/fps;
> + var lastTimeStamp:Number = 0;
> + var timeoutRef:*;
> + var invocations:Array = [];
> + return function(...args):void
> + {
> + invocations.push(args);
> + requestAnimationFrame(callback);
> + function callback(timeStamp:Number):void
> + {
> + if(invocations.length == 0)
> + return;
> +
> + // we can't rely on getting time stamps
> ourselves,
> + // so hopefully this is not slower than
> our target rate...
> + if ( (timeStamp - lastTimeStamp) >=
> limit)
> + {
> + if(lastTimeStamp == 0)
> + lastTimeStamp =
> timeStamp;
> + else
> + lastTimeStamp += limit;
> // make sure we stick to the desired rate
> +
> +
> method.apply(null,invocations.shift());
> + }
> + if(invocations.length)
> + requestAnimationFrame(callback);
> + }
> + }
> + }
> + }
> +}
> \ No newline at end of file
> diff --git
> a/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
> b/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
> index 7b15375..eeb4e76 100644
> --- a/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
> +++ b/frameworks/projects/Core/src/test/royale/flexUnitTests/CoreTester.as
> @@ -45,7 +45,7 @@ package flexUnitTests
> public var sanitizerTest:SanitizeTest;
> public var eventsTest:EventsTest;
> public var objectUtilTests:ObjectUtilsTest;
> - public var functionelTests:FunctionalTests;
> + public var functionalTests:FunctionalTests;
>
> }
> }
> diff --git
> a/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as
> b/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as
> index 022c4da..75f320c 100644
> ---
> a/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as
> +++
> b/frameworks/projects/Core/src/test/royale/flexUnitTests/FunctionalTests.as
> @@ -25,6 +25,8 @@ package flexUnitTests
> import org.apache.royale.test.asserts.*;
> import org.apache.royale.test.async.*;
> import org.apache.royale.utils.functional.*;
> + import org.apache.royale.utils.functional.animateFunction;
> + import org.apache.royale.test.asserts.assertTrue;
>
> public class FunctionalTests
> {
> @@ -192,6 +194,38 @@ package flexUnitTests
> assertEquals(value,7,"value should be 7");
> }, 300);
> }
> + [Test(async,timeout="300")]
> + public function testAnimate():void
> + {
> + var foo:Foo = new Foo();
> + var animateThis:Function = animateFunction(foo.increment,20);
> + for(var i:int=0;i<30;i++){
> + animateThis(1);
> + }
> + var savedThisValue:Number;
> + setTimeout(function():void{
> + savedThisValue = foo.value;
> + },50);
> +
> + var value:Number = 0;
> + function increment(val:Number):void{
> + value+=val;
> + }
> + var animated:Function = animateFunction(increment,20);
> + var savedValue:Number;
> + for(i=0;i<30;i++){
> + animated(1);
> + }
> +
> + setTimeout(function():void{
> + savedValue = value;
> + },50);
> + Async.delayCall(this, function():void
> + {
> + assertTrue(savedThisValue<3,"foo value should be 2");
> + assertTrue(savedValue<3,"value should be 2");
> + }, 300);
> + }
>
>
> }