8 Animation Helpers

▼ |  | Pict: Functional Pictures

1 | Pict Datatype
2 | Basic Pict Constructors
3 | Pict Combiners
4 | Pict Drawing Adjusters
5 | Bounding Box Adjusters
6 | Pict Finders
7 | More Pict Constructors
8 | Animation Helpers
9 | Color Helpers
10 | Shadows
11 | Conditional Combinations
12 | Tree Layout
13 | Miscellaneous
14 | Rendering
15 | Conversion to Picts

► | 8 | Animation Helpers

8.1 | Pict Interpolations
8.2 | Merging Animations
8.3 | Stretching and Squashing Time

On this page:

8.1`` Pict Interpolations
fade-pict
fade-around-pict
slide-pict
slide-pict/ center
8.2`` Merging Animations
sequence-animations
reverse-animations
8.3`` Stretching and Squashing Time
fast-start
fast-end
fast-edges
fast-middle
split-phase

top contents ← prev up next →

### 8`` Animation Helpers🔗ℹ

These functions are designed to work with the slide constructors in slideshow/play.

#### 8.1`` Pict Interpolations🔗ℹ

> > procedure
> > (fade-pict |  | n |  |  |  |
> > |  | p1 |  |  |  |
> > |  | p2 |  |  |  |
> > | [ | #:combine combine |  |  |  |
> > |  | #:composite? composite?]) |  | → |  | pict?
> n : (real-in 0.0 1.0)
> p1 : pict?
> p2 : pict?
> combine : (pict? pict? . -> . pict?) = cc-superimpose
> composite? : any/c = #t

Interpolates p1 and p2, where the result with n as 0.0 is p1, and the result with n as 1.0 is p2. For intermediate points, p1 fades out while p2 fades in as n changes from 0.0 to 1.0. At the same time, the width and height of the generated pict are intermediate between p1 and p2, and the relative baselines and last pict correspondingly morph within the bounding box.

The combine argument determines how p1 and p2 are aligned for morphing. For example, if p1 and p2 both contain multiple lines of text with the same line height but different number of lines, then using ctl-superimpose would keep the ascent line in a fixed location relative to the top of the resulting pict as the rest of the shape morphs around it.

The composite? argument is passed to the cellophane as used to implement fading.

Examples:

> > (define (do-fade n)
> (fade-pict n (rectangle 30 30) (disk 30)))
> > (apply ht-append 10
> (for/list ([n (in-range 0 1.2 0.2)])
> (vc-append (text (~r n #:precision 2))
> (do-fade n))))

Changed in version 1.15 of package pict-lib: Added #:composite? and enabled compositing by default.

> > procedure
> > (fade-around-pict |  | n |  |  |  |
> > |  | p1 |  |  |  |
> > |  | make-p2 |  |  |  |
> > | [ | #:composite? composite?]) |  | → |  | pict?
> n : (real-in 0.0 1.0)
> p1 : pict?
> make-p2 : (pict? . -> . pict?)
> composite? : any/c = #t

Similar to fade-pict, but the target is not a fixed p2, but instead a function make-p2 that takes a laundered ghost of p1 and places it into a larger scene. Also, p1 does not fade out as n increases; instead, p1 is placed wherever its ghost appears in the result of make-p2.

For example,

> > (get-current-code-font-size (λ () 20))
> > (define do-fade
> (lambda (n)
> (fade-around-pict n
> (code x)
> (lambda (g) (code (+ #,g 1))))))
> > (apply ht-append 10
> (for/list ([n (in-range 0 1.2 0.2)])
> (vc-append (text (~r n #:precision 2))
> (do-fade n))))

animates the wrapping of x with a (+ .... 1) form.

Changed in version 1.15 of package pict-lib: Added #:composite? and enabled compositing by default.

> procedure (slide-pict base p p-from p-to n) → pict?
> base : pict?
> p : pict?
> p-from : pict?
> p-to : pict?
> n : (real-in 0.0 1.0)

Pins p onto base, sliding from p-from to p-to (which are picts within base) as n goes from 0.0 to 1.0. The top-left locations of p-from and p-to determine the placement of the top-left of p.

The p-from and p-to picts are typically laundered ghosts of p within base, but they can be any picts within base.

Examples:

> > (define (do-slide n)
> (define p1 (disk 30 #:color "plum"))
> (define p2 (disk 30 #:color "palegreen"))
> (define p3 (frame (inset (hc-append 30 p1 p2) 10)))
> (slide-pict p3
> (disk 10)
> p1 p2 n))
> > (apply ht-append 10
> (for/list ([n (in-range 0 1.2 0.2)])
> (vc-append (text (~r n #:precision 2))
> (do-slide n))))

> procedure (slide-pict/center base p p-from p-to n) → pict?
> base : pict?
> p : pict?
> p-from : pict?
> p-to : pict?
> n : (real-in 0.0 1.0)

Like slide-pict, but aligns the center of p with p-from and p-to.

Examples:

> > (define (do-slide n)
> (define p1 (disk 30 #:color "plum"))
> (define p2 (disk 30 #:color "palegreen"))
> (define p3 (frame (inset (hc-append 30 p1 p2) 10)))
> (slide-pict/center p3
> (disk 10)
> p1 p2 n))
> > (apply ht-append 10
> (for/list ([n (in-range 0 1.2 0.2)])
> (vc-append (text (~r n #:precision 2))
> (do-slide n))))

#### 8.2`` Merging Animations🔗ℹ

> procedure (sequence-animations gen ...) → (-> (real-in 0.0 1.0) pict?)
> gen : (-> (real-in 0.0 1.0) pict?)

Converts a list of gen functions into a single function that uses each gen in sequence.

> procedure (reverse-animations gen ...) → (-> (real-in 0.0 1.0) pict?)
> gen : (-> (real-in 0.0 1.0) pict?)

Converts a list of gen functions into a single function that run (sequence-animations gen ...) in reverse.

#### 8.3`` Stretching and Squashing Time🔗ℹ

> procedure (fast-start n) → (real-in 0.0 1.0)
> n : (real-in 0.0 1.0)
> procedure (fast-end n) → (real-in 0.0 1.0)
> n : (real-in 0.0 1.0)
> procedure (fast-edges n) → (real-in 0.0 1.0)
> n : (real-in 0.0 1.0)
> procedure (fast-middle n) → (real-in 0.0 1.0)
> n : (real-in 0.0 1.0)

Monotonically but non-uniformly maps n with fixed points at 0.0 and 1.0.

Suppose that we have the following definitions for our examples:

> > (define (do-slide n fast-proc)
> (define p1 (filled-rectangle 20 20 #:color "yellowgreen"))
> (define p2 (filled-rectangle 20 20 #:color "khaki"))
> (define p3 (frame (inset (hc-append 25 p1 p2) 10)))
> (slide-pict/center
> p3
> (disk 10)
> p1 p2
> ; note use of fast-proc
> (fast-proc n)))
> > (define (run-animation fast-proc)
> (apply ht-append 10
> (for/list ([n (in-range 0 1.09 0.1)])
> (vc-append (text (~r n #:precision 2))
> (do-slide n fast-proc)))))

A normal use of the animation looks like this:

> > (run-animation (λ (n) n))

The fast-start mapping is convex, so that

> (slide-pict base p p1 p2 (fast-start n))

appears to move quickly away from p1 and then slowly as it approaches p2, assuming that n increases uniformly.

Applying it to the animation above produces this:

> > (run-animation fast-start)

The fast-end mapping is concave, so that

> (slide-pict base p p1 p2 (fast-end n))

appears to move slowly away from p1 and then quickly as it approaches p2, assuming that n increases uniformly.

> > (run-animation fast-end)

The fast-edges mapping is convex at first and concave at the end, so that

> (slide-pict base p p1 p2 (fast-edges n))

appears to move quickly away from p1, then more slowly, and then quickly again near p2, assuming that n increases uniformly.

> > (run-animation fast-edges)

The fast-middle mapping is concave at first and convex at the end, so that

> (slide-pict base p p1 p2 (fast-middle n))

> > (run-animation fast-middle)

appears to move slowly away from p1, then more quickly, and then slowly again near p2, assuming that n increases uniformly.

> > procedure
> > (split-phase n) |  | → |  |
> > (real-in 0.0 1.0) |  | (real-in 0.0 1.0)
> n : (real-in 0.0 1.0)

Splits the progression of n from 0.0 to 1.0 into a progression from (values 0.0 0.0) to (values 1.0 0.0) and then (values 1.0 0.0) to (values 1.0 1.0).

Here is an example that shows how to apply split-phase to the animation from the examples for fast-start:

> > (apply ht-append 10
> (for/list ([n (in-range 0 1.09 0.1)])
> (define-values (n1 n2) (split-phase n))
> (vc-append (text (~r n #:precision 2))
> (do-slide n1 (λ (n) n))
> (do-slide n2 (λ (n) n)))))

top contents ← prev up next →