b-g / ani Goto Github PK
View Code? Open in Web Editor NEWA lightweight animation library for the programming environment Processing
A lightweight animation library for the programming environment Processing
Currently, one has to add the callback to one of the Ani's of the sequence, e.g. the last one for onEnd.
Benedikt,
I'm trying to use Ani with Hype to animate things. But Hype is not relevant for this error. I can't get to animate variables inside an array in a class. Here is log and source code:
Same code works with a variable, but doesn't work with same variable inside an array. I expect s.anims[s.apos]
has same value as alpha
, but it doesn't get affected by Ani.
https://gist.github.com/dandaka/0f6eba3971db74ea938b
Any ideas how to fix that? Thank you!
In the code below (you also can download it) I recreated this strange behavior I'm referring to in the title. All the animations should basically be in sync and start together (if I'm not really mistaken) but they're not. After at last two recreation cycles (of those Stripe objects) this becomes very obvious. And also strange is that the first row on the far left behaves even more independently. When you look close you see a slight lag on the second Stripe (in the row on the left) as soon as the object in front of it ends it's animation.
And yes, I have an application where I need each Stripe object to be able to behave differently, that's why I don't use one single animation for all the Stripe in all rows.
So, what's the reason behind this behavior? Is this a bug? And is there a workaround?
Download pde:
RecreateAniBug.zip
Click inside the sketch window to start animation of Stripe objects.
I set the frameRate to 10 so the effect is more visible.
(I run Processing version: 3.0.2 / Ani library version: 2.7)
`import de.looksgood.ani.*;
ArrayList stripeBundles;
void setup() {
frameRate(10);
size(600, 400, P3D);
background(100);
Ani.init(this);
//Ani.setDefaultTimeMode("FRAMES");
// create 8 StripeBundle objects of which each can have mupltiple Stripe obejects
stripeBundles = new ArrayList();
for (int i = 0; i < 8; i++) {
stripeBundles.add(new StripeBundle(0 + i*60, 0));
}
}
void draw() {
background(100);
if (stripeBundles.get(7).stripes.size() > 0) {
println("seek: "+stripeBundles.get(7).stripes.get(0).posYAni.getSeek());
}
for (StripeBundle sb : stripeBundles) {
sb.run();
// print how many Stripe objects each StripeBundle has (check only first one)
if (stripeBundles.indexOf(sb) == 7)
println("number of Stripe objects: "+stripeBundles.get(stripeBundles.indexOf(sb)).stripes.size());
// add a new Stripe obect to each StripeBundle when animation's seek
// of first Stripe (in the last StripeBundle) is over the half
if (stripeBundles.get(stripeBundles.lastIndexOf(sb)).stripes.size() == 1) {
if (stripeBundles.get(3).stripes.get(0).posYAni.getSeek() > 0.5)
sb.stripes.add( new Stripe(50, height, 80));
}
}
}
void mousePressed() {
// add a new Stripe obect to each StripeBundle
for (StripeBundle sb : stripeBundles) {
sb.stripes.add( new Stripe(50, height, 80));
}
}
class StripeBundle {
float locX, locY;
ArrayList stripes;
StripeBundle(float locX, float locY) {
this.locX = locX;
this.locY = locY;
stripes = new ArrayList();
}
void run() {
for (Stripe s : stripes) {
pushMatrix();
translate(locX, locY);
s.run();
popMatrix();
}
for (int i = stripes.size()-1; i >=0; i--) {
Stripe s = stripes.get(i);
if (!s.alive) stripes.remove(i);
}
}
}
class Stripe {
float h; // height of the "canvas"
float w; // width of the "canvas"
float l; // length of stripe
float posY; // current position of Y
float posX; // position of X
color col; // color of stripe
boolean alive; // remove from ArrayList when not alive
float dur; // duration of posYAni animation
boolean dir; // direction of movement (true: up, flase: down)
float fromY;
float toY;
Ani posYAni; // animation of Y
Stripe(float w, float h, float l) {
this.h = h;
this.w = w;
this.l = l;
this.col = color(255);
this.posY = h/2;
this.posX = w/2;
alive = true;
fromY = -h/2 -l/2;
toY = h/2 +l/2+1;
posY = fromY;
dur = 2;
posYAni = new Ani(this, dur, "posY", toY, Ani.QUAD_IN_OUT);
}
void run() {
update();
display();
}
void update() {
if ( posYAni.isEnded() ) alive = false;
}
void display() {
pushMatrix();
fill(col);
//noStroke();
stroke(0);
rectMode(CENTER);
translate(posX, h/2);
rotate(PI);
rect(0, posY, w, l);
popMatrix();
}
}`
Hello,
I am wondering if there is any ways to use Ani on Android devices?
I tryed with the examples, they build and launch normaly on the device, but then no animation are displayed...
Thanks
I could write down a few suggestion for features I would suggest :) Eventually also particiapte in development (but this depends heavily on my actual workload)
This would allow creating sequences in other classes and then create the final sequence by cascading child sequences. Would be a nice-to-have.
the zip at http://benedikt-gross.de/libraries/Ani/Ani-latest.zip contains a folder called demos
that should be called examples
see: https://github.com/processing/processing/wiki/Library-Guidelines#folder-structure
I am not sure if I am missing something, but here is the simple example when Ani.from doesn't work at all when I set delay greater than 0:
import de.looksgood.ani.*;
float x = 10;
float y = 10;
void setup() {
size(300, 300);
Ani.init(this);
}
void draw() {
background(255);
fill(#ff0000);
ellipse(x, y, 20, 20);
}
void mouseReleased() {
float delay = 1.0; // Ani.from doesn't work for delay > 0
x = 10;
Ani.from(this, 2.0, delay, "x", mouseX);
}
Ani.to(this, 1, 0, "x:1", Ani.SINE_IN_OUT, this, "onStart:onS, onDelayEnd:onD");
should call function onD()
immediately after onS()
. Now onD()
isn't called.
Hi there!
I am working on a simulation, using your sweet animation library. When starting using PVector i found out that the AnimationStyles are not working with PVector unfortunately.
Would be cool if there would be a fix some time.
I tested it with a combination of the EasingViewer and PVector Example:
/**
import de.looksgood.ani.;
import de.looksgood.ani.easing.;
float duration = 1;
PVector point1, target1;
PVector point2, target2;
Easing[] easings = { Ani.LINEAR, Ani.QUAD_IN, Ani.QUAD_OUT, Ani.QUAD_IN_OUT, Ani.CUBIC_IN, Ani.CUBIC_IN_OUT, Ani.CUBIC_OUT, Ani.QUART_IN, Ani.QUART_OUT, Ani.QUART_IN_OUT, Ani.QUINT_IN, Ani.QUINT_OUT, Ani.QUINT_IN_OUT, Ani.SINE_IN, Ani.SINE_OUT, Ani.SINE_IN_OUT, Ani.CIRC_IN, Ani.CIRC_OUT, Ani.CIRC_IN_OUT, Ani.EXPO_IN, Ani.EXPO_OUT, Ani.EXPO_IN_OUT, Ani.BACK_IN, Ani.BACK_OUT, Ani.BACK_IN_OUT, Ani.BOUNCE_IN, Ani.BOUNCE_OUT, Ani.BOUNCE_IN_OUT, Ani.ELASTIC_IN, Ani.ELASTIC_OUT, Ani.ELASTIC_IN_OUT};
String[] easingsVariableNames = {"Ani.LINEAR", "Ani.QUAD_IN", "Ani.QUAD_OUT", "Ani.QUAD_IN_OUT", "Ani.CUBIC_IN", "Ani.CUBIC_IN_OUT", "Ani.CUBIC_OUT", "Ani.QUART_IN", "Ani.QUART_OUT", "Ani.QUART_IN_OUT", "Ani.QUINT_IN", "Ani.QUINT_OUT", "Ani.QUINT_IN_OUT", "Ani.SINE_IN", "Ani.SINE_OUT", "Ani.SINE_IN_OUT", "Ani.CIRC_IN", "Ani.CIRC_OUT", "Ani.CIRC_IN_OUT", "Ani.EXPO_IN", "Ani.EXPO_OUT", "Ani.EXPO_IN_OUT", "Ani.BACK_IN", "Ani.BACK_OUT", "Ani.BACK_IN_OUT", "Ani.BOUNCE_IN", "Ani.BOUNCE_OUT", "Ani.BOUNCE_IN_OUT", "Ani.ELASTIC_IN", "Ani.ELASTIC_OUT", "Ani.ELASTIC_IN_OUT"};
String code = "";
float x = 256;
float y = 256;
int index = 26;
Easing currentEasing = easings[index];
void setup() {
size(800, 600);
smooth();
point1 = new PVector(width/2, height/2);
target1 = new PVector(width/2, height/2);
point2 = new PVector(width/2, height/2);
target2 = new PVector(width/2, height/2);
Ani.init(this);
}
void draw() {
background(250);
Ani.to(point1,duration, "x", target1.x, easings[index]);
Ani.to(point1, duration, "y", target1.y, easings[index]);
Ani.to(point2, 1.0f, "x", target2.x, Ani.ELASTIC_OUT);
Ani.to(point2, 1.0f, "y", target2.y, Ani.ELASTIC_OUT);
noStroke();
fill(255, 0, 0, 128);
ellipse(point1.x, point1.y, 15, 15);
stroke(255, 0, 0, 128);
strokeWeight(2);
noFill();
ellipse(target1.x, target1.y, 20, 20);
noStroke();
fill(0, 0, 255, 128);
ellipse(point2.x, point2.y, 15, 15);
stroke(0, 0, 255, 128);
strokeWeight(2);
noFill();
ellipse(target2.x, target2.y, 20, 20);
code = "Ani.to(this, "+nf(duration,0,2)+", "x", mouseX, "+easingsVariableNames[index]+");";
text(code,10,20);
}
void mousePressed() {
if (mouseButton == LEFT) {
target1.x = mouseX;
target1.y = mouseY;
println("set target1");
}
if (mouseButton == RIGHT) {
target2.x = mouseX;
target2.y = mouseY;
println("set target2");
}
}
void keyPressed() {
if (keyCode == UP) duration += 0.1;
if (keyCode == DOWN) duration -= 0.1;
duration = max(0.25,duration);
}
void keyReleased() {
if (keyCode == LEFT) index--;
if (keyCode == RIGHT) index++;
index = constrain(index,0,easings.length-1);
}
When using Ani in classes and using a bang() or similar method, the applet freezes on occasion. This happened in my own sketch but I was able to reproduce the error in the Ani_in_Classes_Bang example that comes with the library as well. The error is reported at the end of the bang method in the Cirlce class.
import de.looksgood.ani.*;
Cirlce cirlce;
void setup() {
size(512, 512);
smooth();
noStroke();
textAlign(CENTER);
// Ani.init() must be called always first!
Ani.init(this);
cirlce = new Cirlce();
}
void draw() {
background(255);
cirlce.draw();
}
void keyReleased() {
if (key == ' ') cirlce.bang();
}
class Cirlce {
float x = random(0, width);
float y = random(0, height);
color c = color(0);
Ani diameterAni;
float diameterStart = 200;
float diameterEnd = 5;
float diameter = diameterStart;
float duration = 0.9;
Cirlce() {
// diameter animation
diameterAni = new Ani(this, duration, "diameter", diameterEnd);
diameterAni.pause();
diameter = diameterEnd;
}
void bang() {
diameter = diameterStart;
diameterAni.seek(0);
diameterAni.resume();
'Ani_in_Classes_Bang:54:0:54:0: RuntimeException: There is no public this() method in the class de.looksgood.ani.Ani'
}
void draw() {
fill(c);
ellipse(x, y, diameter, diameter);
}
}
Thanks!
When creating a looped sequence, something seems to go wrong if the first item in the sequence has a delay. The issue is not present if other items in the sequence have delays.
Also, only the first variable is affected. In this case it affects only x, but not y or sz.
What seems to happen is, when running seq.start(), the first variable suddenly jumps to the value it should have in the second sequence step (150 instead of 50 in this case).
import de.looksgood.ani.*;
AniSequence seq;
float x=100, y=150, sz=60;
void setup() {
size(600, 600, P2D);
// if delayBug is greater than 0, something goes wrong
float delayBug = 0.0;
Ani.init(this);
seq = new AniSequence(this);
seq.beginSequence();
seq.add(Ani.to(this, 1, delayBug, "x:50.,y:50,sz:40", Ani.QUAD_IN_OUT ));
seq.add(Ani.to(this, 1, 1.0, "x:150,y:50,sz:20", Ani.QUAD_IN_OUT ));
seq.add(Ani.to(this, 1, 1.0, "x:100,y:150,sz:60", Ani.QUAD_IN_OUT, "onEnd:seqEnd"));
seq.endSequence();
seq.start();
}
void draw() {
background(255);
ellipse(x, y, sz, sz);
println(x, y, sz);
}
void seqEnd() {
println("start");
seq.start();
}
Continuing from the post over here: https://forum.processing.org/topic/ani-animation-overrun
Having issues with animations not always ending on the targets I set. It seems to be most prevalent when when using easing and delays.
Here's some sample code:
import de.looksgood.ani.*;
import de.looksgood.ani.easing.*;
float x1, x2, x3, x4, x5;
float y1, y2, y3, y4, y5;
float target;
void setup() {
size(500, 500);
Ani.init(this);
target = 0;
y1 = 0;
y2 = 100;
y3 = 200;
y4 = 300;
y5 = 400;
x1 = 400;
x2 = 400;
x3 = 400;
x4 = 400;
x5 = 400;
}
void draw() {
background(255);
fill(0);
rect(x1, y1, 100, 100);
rect(x2, y2, 100, 100);
rect(x3, y3, 100, 100);
rect(x4, y4, 100, 100);
rect(x5, y5, 100, 100);
}
void mousePressed() {
Ani.to(this, 1, 0.1, "x1", target, Ani.EXPO_IN_OUT);
Ani.to(this, 1, 0.2, "x2", target, Ani.EXPO_IN_OUT);
Ani.to(this, 1, 0.3, "x3", target, Ani.EXPO_IN_OUT);
Ani.to(this, 1, 0.4, "x4", target, Ani.EXPO_IN_OUT);
Ani.to(this, 1, 0.5, "x5", target, Ani.EXPO_IN_OUT);
if(target == 0) {
target = 400;
} else {
target = 0;
}
}
I find that the center square is always a few pixels left of the other four when animating to the right side.
hopefully this helps track down the issue.
Thanks!
ak
I finally managed to create a ArrayList with Easing objects.
But it would be nice if there was something like:
Ani.getAllEasings();
So it can be more convenient to fill an ArrayList.
import de.looksgood.ani.*;
import de.looksgood.ani.easing.Easing;
ArrayList<Easing> easings = new ArrayList<Easing>();
int index = 0;
float x = 256;
float y = 256;
int diameter = 50;
void setup() {
size(512,512);
smooth();
noStroke();
// you have to call always Ani.init() first!
Ani.init(this);
easings.add(Ani.BOUNCE_OUT);
easings.add(Ani.LINEAR);
easings.add(Ani.QUAD_IN);
easings.add(Ani.QUAD_OUT);
easings.add(Ani.QUAD_IN_OUT);
easings.add(Ani.CUBIC_IN);
easings.add(Ani.CUBIC_IN_OUT);
easings.add(Ani.CUBIC_OUT);
easings.add(Ani.QUART_IN);
easings.add(Ani.QUART_OUT);
easings.add(Ani.QUART_IN_OUT);
easings.add(Ani.QUINT_IN);
easings.add(Ani.QUINT_OUT);
easings.add(Ani.QUINT_IN_OUT);
easings.add(Ani.SINE_IN);
easings.add(Ani.SINE_OUT);
easings.add(Ani.SINE_IN_OUT);
easings.add(Ani.CIRC_IN);
easings.add(Ani.CIRC_OUT);
easings.add(Ani.CIRC_IN_OUT);
easings.add(Ani.EXPO_IN);
easings.add(Ani.EXPO_OUT);
easings.add(Ani.EXPO_IN_OUT);
easings.add(Ani.BACK_IN);
easings.add(Ani.BACK_OUT);
easings.add(Ani.BACK_IN_OUT);
easings.add(Ani.BOUNCE_IN);
easings.add(Ani.BOUNCE_OUT);
easings.add(Ani.BOUNCE_IN_OUT);
easings.add(Ani.ELASTIC_IN);
easings.add(Ani.ELASTIC_OUT);
easings.add(Ani.ELASTIC_IN_OUT);
}
void draw() {
background(255);
fill(0);
ellipse(x,y,diameter,diameter);
}
void mouseReleased() {
println("index: "+index);
Ani.to(this, 1.0, "x", mouseX, easings.get(index));
Ani.to(this, 1.0, "y", mouseY, easings.get(index));
}
void keyPressed() {
if (key == '[' || key == '{') {
index--;
}
else if (key == ']' || key == '}') {
index++;
}
index = constrain(index, 0, easings.size()-1);
}
It would be very useful to have callbacks within sequences.
seq.setCallback("myFunction");
This would allow to inject logic inside animations.
Maybe it's already possible but I didn't catch it ?
Thanks for the library ๐
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.