I have a collection of objects that will animate onto screen. I want the random delay of each animation to progressively grow depending on where the item is in the collection.
At the moment I can do this linearly fairly easily like so (Swift).
let proportionThroughContents = CGFloat(Double(idx) / Double(allNodes.count))
let delayRandomiserBaseValue: CGFloat = 40
let delayRandomiserGrowthValue: CGFloat = 60
let delayRandomiserValue = UInt32(delayRandomiserBaseValue + (delayRandomiserGrowthValue * proportionThroughContents))
I actually want some mathematical function to give me a bit of a hockey-stick like effect, where items in the middle still have low values, but items toward the very end get much higher values.
This may be more a mathematical question rather than a programming one, but I feel like this might be common enough to warrant it being here.
There are many possible options. The simplest is probably a quadratic like a x^2 + b x + c
, where x is your proportion and a, b, c are appropriate constants. In code you would need to write this as a*x*x + b*x + c
.
For true exponential functions you want k exp(l x)
in code k * Math.exp(l*x)
.
Choosing the constants is the trickier bit. To get the same initial rates for quadratic just choose b = delayRandomiserGrowthValue
and c = delayRandomiserBaseValue
. You could then choose the a
value depending on how much longer you the delay to be. a + b + c
would give you the maximum delay.
let proportionThroughContents = CGFloat(Double(idx) / Double(allNodes.count))
let delayRandomiserBaseValue: CGFloat = 40 // c
let delayRandomiserGrowthValue: CGFloat = 60 // b
let delayRandomiserQuadraticValue: CGFloat = 60 // a
let delayRandomiserValue = UInt32(delayRandomiserBaseValue
+ delayRandomiserGrowthValue * proportionThroughContents
+ delayRandomiserQuadraticValue * proportionThroughContents * proportionThroughContents )
For exponential k
is the initial value and l*k
is initial growth rate. The final delay would be k e^l
.
let proportionThroughContents = CGFloat(Double(idx) / Double(allNodes.count))
let delayRandomiserBaseValue: CGFloat = 40 // k
let delayRandomiserGrowthValue: CGFloat = 60 //
let l: CGFloat = delayRandomiserGrowthValue / delayRandomiserBaseValue // l
let delayRandomiserValue = UInt32(delayRandomiserBaseValue * Math.exp(l*proportionThroughContents))
With these value l = 60/40 = 1.5
and the maximum delay would be 40*exp(1.5) = 179
.
Thanks for going to the extra effort of applying this to my code sample!
@Salix_alba using the exponential function, is there a way to "move" the curve further towards the end? I have perhaps 200 objects, and I want the last 5 or so to be much slower than the prior.
You might want something more like tan( 2 x / pi). This tends to infinity as x tends towards 1.