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); > + } > > > }