/* Demonstration of the "Penner" easing functions. I've used the Ani library. However you could also copy-paste functions form the source code. This example only uses the functions in the Ani library. The Ani library is really time focused. However with the demo you see how you can add easing on all values between 0.0 - 1.0, and use it for example for music visualisation. - online previz demo http://easings.net/# - cheatsheet https://github.com/b-g/Ani/blob/master/Ani_Cheat_Sheet.pdf Source code: https://github.com/b-g/Ani/tree/master/src/de/looksgood/ani/easing In the code I use the object, but syntax like this also works: float easingOutput = AniConstants.CUBIC_IN_OUT.calcEasing(normalizedValue,0.0,1.0,1.0); In this example code I used normalized values. Which means that we use an value between 0.0 - 1.0 as input and also get that back as output. The functions accept 4 values: // t is time, in this case just 0.0 - 1.0 // b is the start, we just use 0.0 // c is the change, we use normalized so also 1.0 // d is the duration, because we use normalised it's 1.0 30-06-2017: www.kasperkamperman.com */ import de.looksgood.ani.AniConstants; import de.looksgood.ani.easing.*; import de.looksgood.ani.*; Sine sine = new Sine(); Quad quad = new Quad(); Cubic cubic = new Cubic(); Quart quart = new Quart(); Quint quint = new Quint(); Expo expo = new Expo(); Circ circ = new Circ(); Back back = new Back(); Elastic elastic = new Elastic(); Bounce bounce = new Bounce(); // stuff it all in an array for display Easing[] easingFunctions = { sine, quad, cubic, quart, quint, expo, circ, back, elastic, bounce }; String [] easingNames = { "sine", "quad", "cubic", "quart", "quint", "expo", "circ", "back", "elastic", "bounce" }; String [] aniModes = { "IN", "OUT", "IN_OUT" }; int currentAniMode = AniConstants.IN_OUT; float xLeftMargin = 80; float xRightMargin = 80; void setup() { // tip FX2D looks really smooth on retina displays // some things won't work in this mode, but most things do size(640,480,FX2D); noStroke(); changeMode(currentAniMode); } void draw() { background(255); float durationInMilliSeconds = 4000; float normalizedValue = (millis()%durationInMilliSeconds)/durationInMilliSeconds; // overwrite the calculated value when pressing the mouse if(mousePressed) normalizedValue = mouseX/(float)width; fill(0); text("easing mode : " + aniModes[currentAniMode] + " - " + nf(normalizedValue,0,2),10,20); fill(224); rect(xLeftMargin,40,(width-xLeftMargin-xRightMargin),height-80); // line to display the linear 0.0 - 1.0 progress stroke(196); float lineX = xLeftMargin + (normalizedValue * (width-xLeftMargin-xRightMargin)); line(lineX,40,lineX,height-40); for(int i = 0; i < easingFunctions.length; i++) { float yPos = 60+(i*40); float easingOutput = easingFunctions[i].calcEasing(normalizedValue,0.0,1.0,1.0); // put the text in front and draw horizontal line fill(0); text(easingNames[i], 20, yPos); line(xLeftMargin,yPos,(width-xRightMargin),yPos); // draw the eased circle drawCircle(easingOutput, yPos, 20); } text("Press to mouse control the value manually. Change the Ease mode with the 1, 2, 3 keys.", 20, height-15); } void drawCircle(float normalizedValue, float yPos, float radius) { // calculate the x position and take the margins in account float xPos = xLeftMargin + (normalizedValue * (width-xLeftMargin-xRightMargin)); noStroke(); fill(64); ellipse(xPos,yPos,radius,radius); } void keyReleased() { if(key == '1') { changeMode(AniConstants.IN); } else if(key == '2') { changeMode(AniConstants.OUT); } if(key == '3') { changeMode(AniConstants.IN_OUT); } } void changeMode(int mode) { currentAniMode = mode; // change the mode for all easing objects for (Easing e : easingFunctions) { e.setMode(currentAniMode); } }