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, ha...@apache.org 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 <ha...@in-tools.com>
> 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);
> +        }
> 
> 
>     }

Reply via email to