Creating and manipulating animation using APNG fileformat
Overview
The Animated Portable Network Graphics (APNG) file format is an extension to the Portable Network Graphics (PNG) specification. It allows for animated PNG files that work similarly to animated GIF files, while supporting 24-bit images and 8-bit transparency not available for GIFs. It also retains backward compatibility with non-animated PNG files.
1) Export APNG animation to animated GIF
import com.aspose.imaging.Image; | |
import com.aspose.imaging.fileformats.apng.ApngImage; | |
import com.aspose.imaging.imageoptions.GifOptions; | |
try (Image image = Image.load("elephant.png")) | |
{ | |
// Checking the type of loaded image | |
assert (image instanceof ApngImage); | |
// Save to the same format | |
image.save("elephant_same_format.png"); | |
// Export to the other animated format | |
image.save("elephant.png.gif", new GifOptions()); | |
} |
|
|
---|---|
Input image | Result image |
2) Create an animation from multi-page Tiff file
// Example 4. Exporting to APNG file format from other non-animated format | |
import com.aspose.imaging.Image; | |
import com.aspose.imaging.imageoptions.ApngOptions; | |
try (Image image = Image.load("img4.tif")) | |
{ | |
// Setting up the default frame duration | |
ApngOptions options = new ApngOptions(); | |
options.setDefaultFrameTime(500); // 500 ms | |
image.save("img4.tif.500ms.png", options); | |
options.setDefaultFrameTime(250); // 250 ms | |
image.save("img4.tif.250ms.png", options); | |
} |
Result animation:
3) Create APNG animation from single-page image
import com.aspose.imaging.Image; | |
import com.aspose.imaging.RasterImage; | |
import com.aspose.imaging.fileformats.apng.ApngFrame; | |
import com.aspose.imaging.fileformats.apng.ApngImage; | |
import com.aspose.imaging.fileformats.png.PngColorType; | |
import com.aspose.imaging.imageoptions.ApngOptions; | |
import com.aspose.imaging.sources.FileCreateSource; | |
final int AnimationDuration = 1000; // 1 s | |
final int FrameDuration = 70; // 70 ms | |
try (RasterImage sourceImage = (RasterImage) Image.load("not_animated.png")) | |
{ | |
try (ApngOptions createOptions = new ApngOptions()) | |
{ | |
createOptions.setSource(new FileCreateSource("raster_animation.png", false)); | |
createOptions.setDefaultFrameTime(FrameDuration); | |
createOptions.setColorType(PngColorType.TruecolorWithAlpha); | |
try (ApngImage apngImage = (ApngImage) Image.create( | |
createOptions, | |
sourceImage.getWidth(), | |
sourceImage.getHeight())) | |
{ | |
int numOfFrames = AnimationDuration / FrameDuration; | |
int numOfFrames2 = numOfFrames / 2; | |
apngImage.removeAllFrames(); | |
// add first frame | |
apngImage.addFrame(sourceImage, FrameDuration); | |
// add intermediate frames | |
for (int frameIndex = 1; frameIndex < numOfFrames - 1; ++frameIndex) | |
{ | |
apngImage.addFrame(sourceImage, FrameDuration); | |
ApngFrame lastFrame = (ApngFrame) apngImage.getPages()[apngImage.getPageCount() - 1]; | |
float gamma = frameIndex >= numOfFrames2 ? numOfFrames - frameIndex - 1 : frameIndex; | |
lastFrame.adjustGamma(gamma); | |
} | |
// add last frame | |
apngImage.addFrame(sourceImage, FrameDuration); | |
apngImage.save(); | |
} | |
} | |
} |
|
|
---|---|
Source image | Created animation |
4) Create APNG animation using vector graphics
import com.aspose.imaging.Color; | |
import com.aspose.imaging.Image; | |
import com.aspose.imaging.PointF; | |
import com.aspose.imaging.fileformats.apng.ApngImage; | |
import com.aspose.imaging.fileformats.png.PngColorType; | |
import com.aspose.imaging.imageoptions.ApngOptions; | |
import com.aspose.imaging.sources.FileCreateSource; | |
// preparing the animation scene | |
final int SceneWidth = 400; | |
final int SceneHeigth = 400; | |
// Act duration, in milliseconds | |
final long ActDuration = 1000; | |
// Total duration, in milliseconds | |
final long TotalDuration = 4000; | |
// Frame duration, in milliseconds | |
final long FrameDuration = 50; | |
Scene scene = new Scene(); | |
final Ellipse[] ellipse = { new Ellipse() }; | |
ellipse[0].setFillColor(Color.fromArgb(128, 128, 128)); | |
ellipse[0].setCenterPoint(new PointF(SceneWidth / 2f, SceneHeigth / 2f)); | |
ellipse[0].setRadiusX(80); | |
ellipse[0].setRadiusY(80); | |
scene.addObject(ellipse[0]); | |
final Line[] line = { new Line() }; | |
line[0].setColor(Color.getBlue()); | |
line[0].setLineWidth(10); | |
line[0].setStartPoint(new PointF(30, 30)); | |
line[0].setEndPoint(new PointF(SceneWidth - 30, 30)); | |
scene.addObject(line[0]); | |
IAnimation lineAnimation1 = new LinearAnimation(new LinearAnimation.AnimationProgressHandler() { | |
public void invoke(float progress) | |
{ | |
line[0].setStartPoint(new PointF(30 + (progress * (SceneWidth - 60)), 30 + (progress * (SceneHeigth - 60)))); | |
line[0].setColor(Color.fromArgb((int)((progress * 255)), 0, 255 - (int)((progress * 255)))); | |
} | |
}); | |
lineAnimation1.setDuration(ActDuration); | |
IAnimation lineAnimation2 = new LinearAnimation(new LinearAnimation.AnimationProgressHandler() { | |
public void invoke(float progress) | |
{ | |
line[0].setEndPoint(new PointF(SceneWidth - 30 - (progress * (SceneWidth - 60)), 30 + (progress * (SceneHeigth - 60)))); | |
line[0].setColor(Color.fromArgb(255, (int)((progress * 255)), 0)); | |
} | |
}); | |
lineAnimation2.setDuration(ActDuration); | |
IAnimation lineAnimation3 = new LinearAnimation(new LinearAnimation.AnimationProgressHandler() { | |
public void invoke(float progress) | |
{ | |
line[0].setStartPoint(new PointF(SceneWidth - 30 - (progress * (SceneWidth - 60)), SceneHeigth - 30 - (progress * (SceneHeigth - 60)))); | |
line[0].setColor(Color.fromArgb(255 - (int)((progress * 255)), 255, 0)); | |
} | |
}); | |
lineAnimation3.setDuration(ActDuration); | |
IAnimation lineAnimation4 = new LinearAnimation(new LinearAnimation.AnimationProgressHandler() { | |
public void invoke(float progress) | |
{ | |
line[0].setEndPoint(new PointF(30 + (progress * (SceneWidth - 60)), SceneHeigth - 30 - (progress * (SceneHeigth - 60)))); | |
line[0].setColor(Color.fromArgb(0, 255 - (int)((progress * 255)), (int)((progress * 255)))); | |
} | |
}); | |
lineAnimation4.setDuration(ActDuration); | |
SequentialAnimation fullLineAnimation = new SequentialAnimation(); | |
fullLineAnimation.add(lineAnimation1); | |
fullLineAnimation.add(lineAnimation2); | |
fullLineAnimation.add(lineAnimation3); | |
fullLineAnimation.add(lineAnimation4); | |
IAnimation ellipseAnimation1 = new LinearAnimation(new LinearAnimation.AnimationProgressHandler() { | |
public void invoke(float progress) | |
{ | |
ellipse[0].setRadiusX(ellipse[0].getRadiusX() + (progress * 10)); | |
ellipse[0].setRadiusY(ellipse[0].getRadiusY() + (progress * 10)); | |
int compValue = (int)((128 + (progress * 112))); | |
ellipse[0].setFillColor(Color.fromArgb(compValue, compValue, compValue)); | |
} | |
}); | |
ellipseAnimation1.setDuration(ActDuration); | |
IAnimation ellipseAnimation2 = new Delay(); | |
ellipseAnimation2.setDuration(ActDuration); | |
IAnimation ellipseAnimation3 = new LinearAnimation(new LinearAnimation.AnimationProgressHandler() { | |
public void invoke(float progress) | |
{ | |
ellipse[0].setRadiusX(ellipse[0].getRadiusX() - (progress * 10)); | |
int compValue = (int)((240 - (progress * 224))); | |
ellipse[0].setFillColor(Color.fromArgb(compValue, compValue, compValue)); | |
} | |
}); | |
ellipseAnimation3.setDuration(ActDuration); | |
IAnimation ellipseAnimation4 = new LinearAnimation(new LinearAnimation.AnimationProgressHandler() { | |
public void invoke(float progress) | |
{ | |
ellipse[0].setRadiusY(ellipse[0].getRadiusY() - (progress * 10)); | |
int compValue = (int)((16 + (progress * 112))); | |
ellipse[0].setFillColor(Color.fromArgb(compValue, compValue, compValue)); | |
} | |
}); | |
ellipseAnimation4.setDuration(ActDuration); | |
SequentialAnimation fullEllipseAnimation = new SequentialAnimation(); | |
fullEllipseAnimation.add(ellipseAnimation1); | |
fullEllipseAnimation.add(ellipseAnimation2); | |
fullEllipseAnimation.add(ellipseAnimation3); | |
fullEllipseAnimation.add(ellipseAnimation4); | |
ParallelAnimation tmp0 = new ParallelAnimation(); | |
tmp0.add(fullLineAnimation); | |
tmp0.add(fullEllipseAnimation); | |
scene.setAnimation(tmp0); | |
// playing the scene on the newly created ApngImage | |
ApngOptions createOptions = new ApngOptions(); | |
try | |
{ | |
createOptions.setSource(new FileCreateSource("vector_animation.png", false)); | |
createOptions.setColorType(PngColorType.TruecolorWithAlpha); | |
final ApngImage image = (ApngImage) Image.create(createOptions, SceneWidth, SceneHeigth); | |
try | |
/*JAVA: was using*/ | |
{ | |
image.setDefaultFrameTime(FrameDuration); | |
scene.play(image, TotalDuration); | |
image.save(); | |
} | |
finally | |
{ | |
image.close(); | |
} | |
} | |
finally | |
{ | |
createOptions.close(); | |
} | |
/////////////////////////// Scene.java ///////////////////////////// | |
import com.aspose.imaging.fileformats.apng.ApngFrame; | |
import com.aspose.imaging.fileformats.apng.ApngImage; | |
import java.util.ArrayList; | |
/** | |
* <p> | |
* The graphics scene | |
* </p> | |
*/ | |
public class Scene | |
{ | |
/** | |
* <p> | |
* The graphics objects | |
* </p> | |
*/ | |
private final java.util.List<IGraphicsObject> graphicsObjects = new ArrayList<IGraphicsObject>(); | |
/** | |
* <p> | |
* Gets the animation. | |
* </p> | |
*/ | |
public final IAnimation getAnimation() | |
{ | |
return animation; | |
} | |
/** | |
* <p> | |
* Sets the animation. | |
* </p> | |
*/ | |
public final void setAnimation(IAnimation value) | |
{ | |
animation = value; | |
} | |
private IAnimation animation; | |
/** | |
* <p> | |
* Adds the graphics object. | |
* </p> | |
* | |
* @param graphicsObject The graphics object. | |
*/ | |
public final void addObject(IGraphicsObject graphicsObject) | |
{ | |
this.graphicsObjects.add(graphicsObject); | |
} | |
/** | |
* <p> | |
* Plays scene on the specified animation image. | |
* </p> | |
* | |
* @param animationImage The animation image. | |
* @param totalDuration The total duration. | |
*/ | |
public final void play(ApngImage animationImage, long totalDuration) | |
{ | |
/*UInt32*/ | |
long frameDuration = animationImage.getDefaultFrameTime(); | |
/*UInt32*/ | |
long numFrames = (totalDuration / frameDuration); | |
/*UInt32*/ | |
long totalElapsed = 0; | |
for (/*UInt32*/long frameIndex = 0; frameIndex < numFrames; frameIndex++) | |
{ | |
if (this.getAnimation() != null) | |
{ | |
this.getAnimation().update(totalElapsed); | |
} | |
ApngFrame frame = animationImage.getPageCount() == 0 || frameIndex > 0 ? animationImage.addFrame() : (ApngFrame) animationImage.getPages()[0]; | |
com.aspose.imaging.Graphics graphics = new com.aspose.imaging.Graphics(frame); | |
//foreach to while statements conversion | |
for (IGraphicsObject graphicsObject : graphicsObjects) | |
{ | |
graphicsObject.render(graphics); | |
} | |
totalElapsed = (totalElapsed + frameDuration); | |
} | |
} | |
} | |
/////////////////////////// IGraphicsObject.java ///////////////////////////// | |
/** | |
* <p> | |
* The graphics object | |
* </p> | |
*/ | |
public interface IGraphicsObject | |
{ | |
/** | |
* <p> | |
* Renders this instance using specified graphics. | |
* </p> | |
* | |
* @param graphics The graphics. | |
*/ | |
void render(com.aspose.imaging.Graphics graphics); | |
} | |
/////////////////////////// Line.java ///////////////////////////// | |
import com.aspose.imaging.Color; | |
import com.aspose.imaging.Pen; | |
import com.aspose.imaging.PointF; | |
/** | |
* <p> | |
* The line | |
* </p> | |
*/ | |
public class Line implements IGraphicsObject | |
{ | |
/** | |
* <p> | |
* Gets the start point. | |
* </p> | |
* | |
* @return the start point. | |
*/ | |
public final PointF getStartPoint() | |
{ | |
return startPoint.Clone(); | |
} | |
/** | |
* <p> | |
* Sets the start point. | |
* </p> | |
* | |
*/ | |
public final void setStartPoint(PointF value) | |
{ | |
startPoint = value.Clone(); | |
} | |
private PointF startPoint = new PointF(); | |
/** | |
* <p> | |
* Gets the end point. | |
* </p> | |
* | |
*/ | |
public final PointF getEndPoint() | |
{ | |
return endPoint.Clone(); | |
} | |
/** | |
* <p> | |
* Sets the end point. | |
* </p> | |
* | |
*/ | |
public final void setEndPoint(PointF value) | |
{ | |
endPoint = value.Clone(); | |
} | |
private PointF endPoint = new PointF(); | |
/** | |
* <p> | |
* Gets the width of the line. | |
* </p> | |
* | |
*/ | |
public final float getLineWidth() | |
{ | |
return lineWidth; | |
} | |
/** | |
* <p> | |
* Sets the width of the line. | |
* </p> | |
* | |
* @param value the width of the line. | |
*/ | |
public final void setLineWidth(float value) | |
{ | |
lineWidth = value; | |
} | |
private float lineWidth; | |
/** | |
* <p> | |
* Gets the color. | |
* </p> | |
* | |
* @return the color. | |
*/ | |
public final Color getColor() | |
{ | |
return color; | |
} | |
/** | |
* <p> | |
* Sets the color. | |
* </p> | |
* | |
* @param value the color. | |
*/ | |
public final void setColor(Color value) | |
{ | |
color = value.Clone(); | |
} | |
private Color color = new Color(); | |
/** | |
* <p> | |
* Renders this instance using specified graphics. | |
* </p> | |
* | |
* @param graphics The graphics. | |
*/ | |
public final void render(com.aspose.imaging.Graphics graphics) | |
{ | |
graphics.drawLine(new Pen(color, lineWidth), startPoint, endPoint); | |
} | |
} | |
/////////////////////////// Ellipse.java ///////////////////////////// | |
import com.aspose.imaging.Color; | |
import com.aspose.imaging.PointF; | |
import com.aspose.imaging.brushes.SolidBrush; | |
/** | |
* <p> | |
* The ellipse | |
* </p> | |
*/ | |
public class Ellipse implements IGraphicsObject | |
{ | |
/** | |
* <p> | |
* Gets the color of the fill. | |
* </p> | |
* | |
* @return the color of the fill. | |
*/ | |
public final Color getFillColor() | |
{ | |
return fillColor.Clone(); | |
} | |
/** | |
* <p> | |
* Sets the color of the fill. | |
* </p> | |
* | |
* @param value the color of the fill. | |
*/ | |
public final void setFillColor(Color value) | |
{ | |
fillColor = value.Clone(); | |
} | |
private Color fillColor = new Color(); | |
/** | |
* <p> | |
* Gets the center point. | |
* </p> | |
* | |
* @return the center point. | |
*/ | |
public final PointF getCenterPoint() | |
{ | |
return centerPoint.Clone(); | |
} | |
/** | |
* <p> | |
* Sets the center point. | |
* </p> | |
* | |
* @param value the center point. | |
*/ | |
public final void setCenterPoint(PointF value) | |
{ | |
centerPoint = value.Clone(); | |
} | |
private PointF centerPoint = new PointF(); | |
/** | |
* <p> | |
* Gets the radius x. | |
* </p> | |
* | |
* @return the radius x. | |
*/ | |
public final float getRadiusX() | |
{ | |
return radiusX; | |
} | |
/** | |
* <p> | |
* Sets the radius x. | |
* </p> | |
* | |
* @param value the radius x. | |
*/ | |
public final void setRadiusX(float value) | |
{ | |
radiusX = value; | |
} | |
private float radiusX; | |
/** | |
* <p> | |
* Gets the radius y. | |
* </p> | |
* | |
* @return the radius y. | |
*/ | |
public final float getRadiusY() | |
{ | |
return radiusY; | |
} | |
/** | |
* <p> | |
* Sets the radius y. | |
* </p> | |
* | |
* @param value the radius y. | |
*/ | |
public final void setRadiusY(float value) | |
{ | |
radiusY = value; | |
} | |
private float radiusY; | |
/** | |
* <p> | |
* Renders this instance using specified graphics. | |
* </p> | |
* | |
* @param graphics The graphics. | |
*/ | |
@Override | |
public final void render(com.aspose.imaging.Graphics graphics) | |
{ | |
graphics.fillEllipse(new SolidBrush(fillColor), centerPoint.getX() - radiusX | |
, centerPoint.getY() - radiusY, radiusX * 2, radiusY * 2); | |
} | |
} | |
/////////////////////////// IAnimation.java ///////////////////////////// | |
/** | |
* <p> | |
* The animation | |
* </p> | |
*/ | |
public interface IAnimation | |
{ | |
/** | |
* <p> | |
* Gets the duration. | |
* </p> | |
* | |
* @return the duration. | |
*/ | |
long getDuration(); | |
/** | |
* <p> | |
* Sets the duration. | |
* </p> | |
* | |
* @param value the duration. | |
*/ | |
void setDuration(long value); | |
/** | |
* <p> | |
* Updates the animation progress. | |
* </p> | |
* | |
* @param elapsed The elapsed time, in milliseconds. | |
*/ | |
void update(long elapsed); | |
} | |
/////////////////////////// LinearAnimation.java ///////////////////////////// | |
/** | |
* <p> | |
* The linear animation | |
* </p> | |
*/ | |
public class LinearAnimation implements IAnimation | |
{ | |
/** | |
* <p> | |
* The progress handler | |
* </p> | |
*/ | |
private final AnimationProgressHandler progressHandler; | |
/** | |
* <p> | |
* Animation progress handler delegate | |
* </p> | |
*/ | |
public interface AnimationProgressHandler | |
{ | |
/** | |
* <p> | |
* Animation progress handler delegate | |
* </p> | |
* | |
* @param progress The progress, in [0;1] range. | |
*/ | |
void invoke(float progress); | |
} | |
/** | |
* <p> | |
* Initializes a new instance of the {@link LinearAnimation} class. | |
* </p> | |
* | |
* @param progressHandler The progress handler. | |
* @throws NullPointerException progressHandler is null. | |
*/ | |
public LinearAnimation(AnimationProgressHandler progressHandler) | |
{ | |
if (progressHandler == null) | |
{ | |
throw new NullPointerException("progressHandler"); | |
} | |
this.progressHandler = progressHandler; | |
} | |
/** | |
* <p> | |
* Gets the duration. | |
* </p> | |
* | |
* @return the duration. | |
*/ | |
@Override | |
public final long getDuration() | |
{ | |
return duration; | |
} | |
/** | |
* <p> | |
* Sets the duration. | |
* </p> | |
* | |
* @param value the duration. | |
*/ | |
@Override | |
public final void setDuration(long value) | |
{ | |
duration = value; | |
} | |
private long duration; | |
/** | |
* <p> | |
* Updates the animation progress. | |
* </p> | |
* | |
* @param elapsed The elapsed time, in milliseconds. | |
*/ | |
@Override | |
public final void update(long elapsed) | |
{ | |
if (elapsed <= duration) | |
{ | |
this.progressHandler.invoke((float) elapsed / duration); | |
} | |
} | |
} | |
/////////////////////////// Delay.java ///////////////////////////// | |
/** | |
* <p> | |
* The simple delay between other animations | |
* </p> | |
*/ | |
public class Delay implements IAnimation | |
{ | |
/** | |
* <p> | |
* Gets the duration. | |
* </p> | |
* | |
* @return the duration. | |
*/ | |
@Override | |
public final long getDuration() | |
{ | |
return duration; | |
} | |
/** | |
* <p> | |
* Sets the duration. | |
* </p> | |
* | |
* @param value the duration. | |
*/ | |
@Override | |
public final void setDuration(long value) | |
{ | |
duration = value; | |
} | |
private long duration; | |
/** | |
* <p> | |
* Updates the animation progress. | |
* </p> | |
* | |
* @param elapsed The elapsed time, in milliseconds. | |
*/ | |
@Override | |
public final void update(long elapsed) | |
{ | |
// Do nothing | |
} | |
} | |
/////////////////////////// ParallelAnimation.java ///////////////////////////// | |
import java.util.ArrayList; | |
import java.util.Collection; | |
/** | |
* <p> | |
* The parallel animation processor | |
* </p> | |
*/ | |
public class ParallelAnimation extends ArrayList<IAnimation> implements IAnimation | |
{ | |
/** | |
* <p> | |
* Initializes a new instance of the {@link ParallelAnimation} class. | |
* </p> | |
*/ | |
public ParallelAnimation() | |
{ | |
// Do nothing | |
} | |
/** | |
* <p> | |
* Initializes a new instance of the {@link ParallelAnimation} class. | |
* </p> | |
* | |
* @param animations The animations. | |
*/ | |
public ParallelAnimation(Collection<IAnimation> animations) | |
{ | |
super(animations); | |
} | |
/** | |
* <p> | |
* Gets the duration. | |
* </p> | |
* | |
* @return the duration. | |
*/ | |
@Override | |
public final long getDuration() | |
{ | |
long maxDuration = 0; | |
for (IAnimation animation : this) | |
{ | |
if (maxDuration < animation.getDuration()) | |
{ | |
maxDuration = animation.getDuration(); | |
} | |
} | |
return maxDuration; | |
} | |
/** | |
* <p> | |
* Sets the duration. | |
* </p> | |
* | |
* @param value the duration. | |
*/ | |
@Override | |
public final void setDuration(long value) | |
{ | |
throw new UnsupportedOperationException(); | |
} | |
/** | |
* <p> | |
* Updates the animation progress. | |
* </p> | |
* | |
* @param elapsed The elapsed time, in milliseconds. | |
*/ | |
@Override | |
public final void update(long elapsed) | |
{ | |
for (IAnimation animation : this) | |
{ | |
animation.update(elapsed); | |
} | |
} | |
} | |
/////////////////////////// SequentialAnimation.java ///////////////////////////// | |
import java.util.ArrayList; | |
import java.util.Collection; | |
/** | |
* <p> | |
* The sequential animation processor | |
* </p> | |
*/ | |
public class SequentialAnimation extends ArrayList<IAnimation> implements IAnimation | |
{ | |
/** | |
* <p> | |
* Initializes a new instance of the {@link SequentialAnimation} class. | |
* </p> | |
*/ | |
public SequentialAnimation() | |
{ | |
// Do nothing | |
} | |
/** | |
* <p> | |
* Initializes a new instance of the {@link SequentialAnimation} class. | |
* </p> | |
* | |
* @param animations The animations. | |
*/ | |
public SequentialAnimation(Collection<IAnimation> animations) | |
{ | |
super(animations); | |
} | |
/** | |
* <p> | |
* Gets the duration. | |
* </p> | |
* | |
* @return the duration. | |
*/ | |
@Override | |
public final long getDuration() | |
{ | |
/*UInt32*/ | |
long summDuration = 0; | |
for (IAnimation animation : this) | |
{ | |
summDuration = summDuration + animation.getDuration(); | |
} | |
return summDuration; | |
} | |
/** | |
* <p> | |
* Sets the duration. | |
* </p> | |
* | |
* @param value the duration. | |
*/ | |
@Override | |
public final void setDuration(long value) | |
{ | |
throw new UnsupportedOperationException(); | |
} | |
/** | |
* <p> | |
* Updates the animation progress. | |
* </p> | |
* | |
* @param elapsed The elapsed time, in milliseconds. | |
*/ | |
@Override | |
public final void update(long elapsed) | |
{ | |
long totalDuration = 0; | |
for (IAnimation animation : this) | |
{ | |
if (totalDuration > elapsed) | |
{ | |
break; | |
} | |
animation.update((elapsed - totalDuration)); | |
totalDuration = totalDuration + animation.getDuration(); | |
} | |
} | |
} |
Created from graphics animation: