Do you remember The Matrix movies, that started coming out in 1999? Hopefully this movie franchise didn't give you a fear of virtual reality and AI. The thing I remember most from the movie was the really cool slow-motion video effects (from multiple angles) in the fight scenes. And the second most cool thing was the computer code scrolling/dripping/raining down from the top of the screen. It's this second cool thing that I decided to try to imitate with my own code - follow along to see how ...
First, here's a small example to get you into the spirit of things. Without any hints about how I have ordered/offset/colored the text, can you guess which (famous) text I used in this version of the animation? Feel free to leave your guess in the comments (I'll tell the answer at the end of the blog).
How about some hints? ... Here are some general rules I applied to my text file, to create the animation:
- Each row of text goes in a single column.
- The rows of text are ordered left-to-right in the animation, they same as they were ordered top-to-bottom in the text file.
- The text line is angled 90 degrees, and each character is rotated -90 degrees (so you can read the text line from bottom-to-top).
- I staggered the lines, such that each one starts at a slightly different place.
- I padded the staggered lines with blanks, and set up the animation so it is an endless loop (no beginning and no ending).
- The coloring is random (each line of text is randomly assigned 1 of the 4 color shades).
Knowing these rules, are you now able to read the animation, and figure out what the text is? (Give it a try!)
Now, let's dive into the SAS code! First, I wrote a macro (subroutine) that lets me pass in the name of the text file, and a few other parameters. This makes it easy to re-use the code, to animate other text files.
%macro do_matrix(textfile, maxlen, maxobs, ypix, nametext);
Next I read in the text file, and exclude a few of the short lines that often appear in my code (yes, I animate some of my code later on).
filename myfile "&textfile";
data textdata;
infile myfile ls=&maxlen pad;
length textline $ &maxlen;
input textline $ 1-&maxlen;
if trim(left(textline)) not in ('' '/*' '*/' 'run;' ';' 'quit;' 'quit; run;') then output;
run;
I chop up the lines of text, and start each one at a different random position in the text, and pad the lines with spaces ('a0'x). This way, I can wrap them around from the top to the bottom of the screen.
data textdata; set textdata;
orginal_obs=_n_;
length=length(trim(left(textline)));
textline=translate(textline,'a0'x,' ');
random_color_num=ranuni(123);
startloc=.; startloc=int(ranuni(123)*&maxlen);
length modline $&maxlen;
modline=substr(textline,startloc);
modline=trim(modline)||substr(textline,1,startloc-1);
run;
I loop through the characters of each line, and keep calculating a different starting place, and chop the text off one end of the line, and append it to the other end. At each iteration, the counter is named 'loop'.
do loop = 2 to &maxlen by 1;
temp=substr(modline,loop);
temp=trim(temp)||substr(modline,1,loop-1);
text=temp;
output;
end;
I generate a scatter plot, and annotate the text on it 'by loop', creating a different scatter plot for each frame of the animation. I suppress all the axes, and anything that looks like a scatter plot, so all you see is the animated text.
title;
footnote;
symbol1 value=none interpol=none color=black;
axis1 label=none c=gray33 style=0 major=none minor=none value=none;
proc gplot data=annotext /*anno=annotext*/;
by loop;
plot y*x=1 /
cframe=gray33
vaxis=axis1 haxis=axis1
anno=annotext
des='' name="&name._&nametext";
run;
And I use these options, to knit all the separate plots into a single gif animation.
options dev=sasprtc printerpath=gif animduration=.25 animloop=0
animoverlay=no animate=start center nobyline;
And here's a screen-capture of another animation. Can you guess which text file it was? The gif animation file was bigger than the 1MB maximum size to upload into the blog, but you can click the screen-capture to see the animation in a separate window. Also, here's a link to the full SAS code, if you're interested in creating a similar animation using text from your own text files.
Answers:
The first animation was The Star Spangled Banner (National Anthem).
The second animation was the SAS code used to create the animation.
1 Comment
Hi Robert,
recently saw an example of "scrollytelling" - like this one:
https://www.nytimes.com/interactive/2014/06/20/sports/worldcup/how-world-cup-players-are-connected.html
Would be most interested in finding out how something like this could be created in SAS
David