Skip to content

Animation

Scott Pakin edited this page Mar 24, 2023 · 4 revisions

Although Inkscape itself does not render animations, Simple Inkscape Scripting makes it easy to construct SMIL-based SVG animations that can be viewed in a Web browser.

The key concept behind Simple Inkscape Scripting's approach is that an object can be given one or more other objects whose parameters, styles, and transformations it will adopt in sequence. This is implemented with a single method defined on the shape objects created by the functions described in Shape construction:

Method: animate(objs, duration, begin_time, key_times, repeat_count, repeat_time, keep, interpolation, path, path_rotate, at_end, attr_filter)

Although animate accepts a large number of arguments, all of them are optional, and typically only a few are needed to implement a desired animation sequence. In the following description, the "target object" is the object on which the animate method is invoked and that will be animated.

  • objs. A shape object or list of shape objects whose properties will be applied in turn to the target object. Simple Inkscape Scripting automatically identifies properties in common but with varying values across all objects. These are the properties that are animated. In common usage at least one object must be supplied. (The exception is in path animations; see path below.)

  • duration. The length of time from the start to the end of the animation, commonly expressed as a floating-point number of seconds with a suffix of ms (milliseconds), s (seconds), min (minutes), or h (hours). It can also be expressed in the form [HH]:MM:SS[.ss]. In common usage, duration is specified. (The exception is if key_times is specified instead.)

  • begin_time. A delay from when the SVG file is loaded until the animation begins (default: 0s). Times are specified as in duration, above.

  • key_times. A list of fractional time offsets (from 0.0 to 1.0) at which each object's properties should be fully applied. The list must contain exactly the number of elements as there are objects in objs plus one for the target object. For example, a.animate([b, c], duration='5s', key_times=[0.0, 0.25, 1.0]) will cause object a to have its initial properties at time 0s (5s·0.0), b's properties at time 1.25s (5s·0.25), and c's properties at time 5s (5s·1.0). Transitions are gradual by default (but see interpolation below); hence, at time 0.625s, a will have a blend of 50% of its original properties and 50% of b's properties.

  • repeat_count. The number of times the animation should be performed (default: 1). The count must be either a positive integer or the string indefinite to repeat the animation indefinitely.

  • repeat_time. The length of time the animation should be performed (default: same as duration). Times are specified as in duration, above, or can be the string indefinite to repeat the animation indefinitely. The animation will repeat for the given length of time then stop abruptly (even in the middle of the sequence).

  • keep. Whether to keep the target object's final state when the animation completes (default: True). If keep is True, the final state is kept; if it's False, the target object is reset to its original state.

  • interpolation. A string indicating how to interpolate from each object to the next (default: linear for most attributes, paced for motion paths). If interpolation is linear, properties change linearly. If interpolation is paced, properties change according to the distance traveled along a path. If interpolation is discrete, properties change abruptly from each object to the next.

  • path. Define a motion path for the object to follow. The argument should be an object created with Simple Inkscape Scripting's path function (see Shape construction#Paths).

  • path_rotate. The angle in degrees at which to rotate the target object as it follows the motion path defined with path, above (default: 0). It can also be the string auto to orient the object's right side tangent to the path at all points along the path or the string auto-reverse to orient the object's left side tangent to the path at all points along the path.

  • at_end. Whether to treat the target object as the first object in the sequence (False, the default) or the last object in the sequence (True). For example, a.animate([b, c], duration='5s', at_end=False) displays a's properties, then b's properties, then c's properties. In contrast, a.animate([b, c], duration='5s', at_end=True) displays b's properties, then c's properties, and finally a's properties.

  • attr_filter. A function that maps an attribute name to a Boolean, indicating whether that attribute should be animated (default: lambda a: True). Attributes are either SVG shape attributes (e.g., cx, cy, and r for a circle), SVG style names (e.g., stroke-width) or SVG transform functions (specifically, translate, rotate, and scale). For example, attr_filter=lambda a: a in ['width', 'height'] allows a rectangle's width and height to be animated but ignores changes to all other properties.

Example:

def make_rect(center, fill, edge=100):
    return rect(inkex.Vector2d(-edge/2, -edge/2) + center,
                inkex.Vector2d(edge/2, edge/2) + center,
                fill=fill)

r1 = make_rect((50, 50), '#aade87')
r2 = make_rect((canvas.width/2, canvas.height/2), '#9955ff')
r3 = make_rect((canvas.width - 50, canvas.height - 50), '#d35f5f')

r1.animate([r2, r3], duration='3s')

animate

The preceding example moves a rectangle from the upper-left corner of the page to the center to the lower-right corner, changing its color as it moves.

Using that example as a base, the following variations alter only the final line of code to demonstrate different features of Simple Inkscape Scripting animation. To start, the following shows how to use at_end to change the direction of animation from r1r2r3 to r3r2r1 even though r1 remains the target object:

r1.animate([r3, r2], duration='3s', at_end=True)

The next variation renders the changes from r1 to r2 to r3 in discrete jumps instead of continuously:

r1.animate([r2, r3], duration='3s', interpolation='discrete')

One can specify key times to change slowly from r1 to r2 (in 3s·(0.75 - 0) = 2.25s) then quicker from r2 to r3 (in 3s·(1 - 0.75) = 0.75s):

r1.animate([r2, r3], duration='3s', key_times=[0, 0.75, 1])

There are two ways to specify repetition of an animation sequence. First, repeat_count specifies the number of times to perform the sequence:

r1.animate([r2, r3], duration='3s', repeat_count=2)

Second, repeat_time performs the sequence for a given length of time, stopping in the middle of the sequence if time runs out:

r1.animate([r2, r3], duration='3s', repeat_time='5s')

Both repeat_count and repeat_time support repeating the animation sequence indefinitely:

r1.animate([r2, r3, r2, r1], duration='3s', repeat_count='indefinite')

The start of an animation can be delayed by specifying a begin_time:

r1.animate(r2, duration='2s')
r3.animate(r2, duration='2s', begin_time='2s')

The following lines demonstrate two Simple Inkscape Scripting animation features. First, they show that animate can be invoked repeatedly on a target object. Second, they show how to use attr_filter to transition r1's position to r2's, ignoring the differences in color, then use attr_filter in a second animation to transition the rest of r1's attributes (just color in this case) to r3's.

r1.animate(r2, duration='2s', attr_filter=lambda a: a in ['x', 'y'])
r1.animate(r3, duration='4s', attr_filter=lambda a: a not in ['x', 'y'])

Finally, object transforms can also be animated, as demonstrated by the following, which creates an r4 that is scaled, rotated, and translated, and transitions r1 to use that transform. Delete the base example's definitions of r2 and r3 first, as those rectangles are not used here.

r4 = make_rect((0, 0), '#5599ff')
r4.transform = 'translate(%.5f, %.5f) rotate(200) scale(2)' % (canvas.width/2, canvas.height/2)
r1.animate(r4, duration='3s')

animate-transform

Clone this wiki locally