On this page:
5.1 Generating Animated Slides
play
play-n
animate-slide
5.2 Animation Helpers
fade-pict
fade-around-pict
slide-pict
5.3 Merging Animations
sequence-animations
reverse-animations
5.4 Stretching and Squashing Time
fast-start
fast-end
fast-edges
fast-middle
split-phase

5 Animations

The slideshow/play module provides tools for generating animations as multiple, automatically advanced slides.

Many of the tools are based on a function that takes a number between 0.0 and 1.0 inclusive and produces a pict. The pict produced for the input 0.0 is the starting image of the animation, and the pict produced for 1.0 is the ending image, while intermediate values produced intermediate images. For example,

(lambda (n)
  (cellophane (t "Hello") n))

corresponds to an animation that fades in the word “Hello.”

5.1 Generating Animated Slides

(play gen    
  [#:steps steps    
  #:delay delay-secs    
  #:skip-first? skip-first?    
  #:title title    
  #:name name    
  #:layout layout])  void?
  gen : ((real-in 0.0 1.0) . -> . pict?)
  steps : exact-positive-integer? = 10
  delay-secs : real? = 0.05
  skip-first? : any/c = #f
  title : 
(or/c string? pict? #f
      ((real-in 0.0 1.0) . -> . (or/c string? pict? #f)))
   = #f
  name : 
(or/c string? #f
      ((real-in 0.0 1.0) . -> . (or/c string? #f)))
   = title
  layout : (or/c 'auto 'center 'top 'tall) = 'auto
Generates steps+1 slides by calling gen on equally-spaced values from 0.0 (inclusve) to 1.0 (exclusive). Except for the first of the slides, each slide has a timeout of delay-secs, so that the next slide appears automatically.

Normally, play is called via play-n, which effectively calls gen on 1.0 without a timeout to complete the animation and stop the auto-advance of slides. The play-n function also manages with multi-step animations.

If skip-first? is #f, then one fewer slide is generated, because gen is not called on 0.0.

The title, name, and layout arguments are passed on to slide, at least when title and/or name are not functions. When title or name is a function, the function is applied to the value used to produce the slide content, and the resulting title or name is passed on to slide.

In condensed mode (i.e., when condense? is #t), any slide that would be registered with a timeout is instead skipped.

(play-n gen*    
  [#:steps steps    
  #:delay delay-secs    
  #:skip-first? skip-first?    
  #:skip-last? skip-last?    
  #:title title    
  #:name name    
  #:layout layout])  void?
  gen* : (() (listof (real-in 0.0 1.0)) . ->* . pict?)
  steps : 
(or/c exact-positive-integer?
      (improper-listof exact-positive-integer?))
 = 10
  delay-secs : real? = 0.05
  skip-first? : any/c = #f
  skip-last? : any/c = #f
  title : 
(or/c string? pict? #f
      ((real-in 0.0 1.0) . -> . (or/c string? pict? #f)))
   = #f
  name : 
(or/c string? #f
      ((real-in 0.0 1.0) . -> . (or/c string? #f)))
   = title
  layout : (or/c 'auto 'center 'top 'tall) = 'auto
Generates a sequence of slides by calling gen* with, for each of its arguments, numbers from 0.0 to 1.0. If gen* accepts n arguments, then result is a sequence of animations with a pause (i.e., not auto-advanced) between each of n segments.

If gen* accepts a single argument, then play-n is like play, except that gen* is also called with 1.0 to generate a slide with no timeout. If gen* accepts multiple arguments, then slides are generated by calling gen* with the first argument varying from 0.0 to 1.0 while all other arguments are 0.0. Then, the first argument is held at 1.0 while the second argument varies from 0.0 to 1.0, and so on.

For example,

(play-n
 (lambda (n1 n2)
   (cellophane (t "Hello")
               (* n1 (- 1.0 n2)))))

generates an animation to fade in the word “Hello,” and then pauses for a manual advance, and then fades “Hello” back out.

If skip-first? is #t, then the very first slide of the sequence is skipped. Similarly, if skip-last? is #t, then the last slide of the sequence is skipped.

The steps argument controls how many steps happen in each phase on the animation. If it is a number, then that number is used for each phase. If it is a pair of two numbers, then the first number is used for the first phase, and the second number is used for the rest of the phases. Similarly, if it is (cons num_1 (cons num_2 num_3)), num_1 and num_2 are used for the first two phases and num_3 is used for the rest.

The delay-msecs, title, name, and layout arguments are passed on to play for each of the n segments of animation.

(animate-slide element ...)
  (() (listof (real-in 0.0 1.0)) . ->* . pict?)
  element : 
(flat-rec-contract elem/c
  (or/c pict? 'next 'alts
       (listof (listof elem/c))))
Accepts slide content similar to slide with 'next and 'alts and produces a procedure suitable for use with play-n. The result is similar to using slide, but with fades for 'next and 'alts transitions (to better fit the style, perhaps, of surrounding animations).

5.2 Animation Helpers

(fade-pict n p1 p2 [#:combine combine])  pict?
  n : (real-in 0.0 1.0)
  p1 : pict?
  p2 : pict?
  combine : (pict? pict? . -> . pict?) = cc-superimpose
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.

(fade-around-pict n p1 make-p2)  pict?
  n : (real-in 0.0 1.0)
  p1 : pict?
  make-p2 : (pict? . -> . pict?)
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,

(lambda (n)
  (fade-around-pict n
                    (code x)
                    (lambda (g) (code (+ #,x 1)))))

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

(slide-pict base p p-from p-to n)  pict?
  base : pict?
  p : pict?
  p-from : pict?
  p-to : pict?
  n : (in-real 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.

5.3 Merging Animations

(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.

(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.

5.4 Stretching and Squashing Time

(fast-start n)  (in-real 0.0 1.0)
  n : (in-real 0.0 1.0)
(fast-end n)  (in-real 0.0 1.0)
  n : (in-real 0.0 1.0)
(fast-edges n)  (in-real 0.0 1.0)
  n : (in-real 0.0 1.0)
(fast-middle n)  (in-real 0.0 1.0)
  n : (in-real 0.0 1.0)
Monotonically but non-uniformly maps n with fixed points at 0.0 and 1.0.

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.

The fast-end mapping is concave, so that

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

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

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

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

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

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

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

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

(split-phase n)  
(in-real 0.0 1.0) (in-real 0.0 1.0)
  n : (in-real 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).