The following sample programs generate animated GIFs:
Sample Animated GIF, with HTML from PUT Statements on page 460
Generating an Animated Web Presentation with the GIFANIM Device Driver on page 463
The following sample program generates an animated GIF from a SAS data set and two invocations of PROC GCHART, each of which contains a BY statement.
Results Shown in a Browser on page 460
SAS Code on page 460
HTML File on page 463
The following picture shows only the first picture of the animated GIF. After a specified time lapse, the chart for each quarter of each of the two years is displayed in turn .
The following is the complete SAS code to generate the animated GIF and an HTML file that references it. You should notice the following:
The GSFNAME= option of the GOPTIONS statement specifies the name of the GIF to be created. In this example, the value of GSFNAME is specified in an associated FILENAME statement. If you want to run this example, then change the value of the FILENAME statement to something that makes sense for you.
The following statement
goptions gsfmode=append;
is included before the second invocation of PROC GCHART so that the output is appended to the same GIF file.
A FILE statement specifies the complete path and file name of the HTML file to be created by the PUT statements. If you want to run this example, then change the value to something that makes sense for you
data prdsummary; input Year Quarter Country $ Product $ Actual dollar10.2; label Actual = 'Actual Sales'; format Actual dollar11.; datalines; 1993 1 CANADA BED ,337.00 1993 1 CANADA CHAIR ,115.00 1993 1 CANADA DESK ,644.00 1993 1 GERMANY BED ,026.00 1993 1 GERMANY CHAIR ,276.00 1993 1 GERMANY DESK ,330.00 1993 2 CANADA BED ,437.00 1993 2 CANADA CHAIR ,115.00 1993 2 CANADA DESK ,654.00 1993 2 GERMANY BED ,026.00 1993 2 GERMANY CHAIR ,276.00 1993 2 GERMANY DESK ,320.00 1993 3 CANADA BED ,337.00 1993 3 CANADA CHAIR ,145.00 1993 3 CANADA DESK ,614.00 1993 3 GERMANY BED ,026.00 1993 3 GERMANY CHAIR ,276.00 1993 3 GERMANY DESK ,340.00 1993 4 CANADA BED ,337.00 1993 4 CANADA CHAIR ,115.00 1993 4 CANADA DESK ,646.00 1993 4 GERMANY BED ,026.00 1993 4 GERMANY CHAIR ,276.00 1993 4 GERMANY DESK ,350.00 1994 1 CANADA BED ,327.00 1994 1 CANADA CHAIR ,345.00 1994 1 CANADA DESK ,624.00 1994 1 GERMANY BED ,026.00 1994 1 GERMANY CHAIR ,276.00 1994 1 GERMANY DESK ,340.00 1994 2 CANADA BED ,356.00 1994 2 CANADA CHAIR ,115.00 1994 2 CANADA DESK ,623.00 1994 2 GERMANY BED ,026.00 1994 2 GERMANY CHAIR ,276.00 1994 2 GERMANY DESK ,321.00 1994 3 CANADA BED ,321.00 1994 3 CANADA CHAIR ,115.00 1994 3 CANADA DESK ,658.00 1994 3 GERMANY BED ,026.00 1994 3 GERMANY CHAIR ,276.00 1994 3 GERMANY DESK ,398.00 1994 4 CANADA BED ,357.00 1994 4 CANADA CHAIR ,166.00 1994 4 CANADA DESK ,662.00 1994 4 GERMANY BED ,026.00 1994 4 GERMANY CHAIR ,246.00 1994 4 GERMANY DESK ,329.00 ; /* delete previously created gsegs before creating new ones */ /* (SAS creates gsegs before creating gifs from them */ proc greplay igout=work.gseg nofs; delete _all_; /* could also specify: delete _1993, _19931, etc. */ run; quit; /* use filename to specify output folder for gif files */ filename myimages 'u:\public_html\Web_output\gifanim.gif'; goptions reset=all device=gifanim gsfname=myimages gsfmode=replace /* not necessary when using "BY" */ delay=150 /* set delay between images */ border ftext="Helvetica" ftitle="Helvetica"; title1 '1993 Sales'; proc gchart data=prdsummary(where=(year=1993)); hbar3d country / sumvar=actual subgroup=product sum shape=hexagon caxis=black cframe=CXb0c1f4; by quarter; run; quit; goptions gsfmode=append; title1 '1994 Sales'; proc gchart data=prdsummary(where=(year=1994)); hbar3d country / sumvar=actual subgroup=product sum shape=hexagon caxis=black cframe=CXb0c1f4; by quarter; run; quit; data _null_ ; file 'u:\public_html\Web_output\gifanim.htm' ; put '<HTML>'; put '<HEAD>'; put '<TITLE> GIFANIM </TITLE>'; put '</HEAD>'; put '<BODY>'; put '<IMG src="gifanim.gif">'; put '</BODY>'; put '</HTML>'; run;
The following is the HTML file that is generated by the PUT statements. Of course, instead of embedding PUT statements in a SAS program, you can hand-create your own HTML file using whatever editor you prefer.
<HTML> <HEAD> <TITLE> GIFANIM </TITLE> </HEAD> <BODY> <IMG src="gifanim.gif"> </BODY> </HTML>
This example uses the GIFANIM device driver to generate an output file in GIF format. A simple HTML file is also created, using PUT statements. The HTML file enables you to display the GIF file in a Web browser. The browser displays a continuous loop of ten maps of the state of North Carolina, one of which is shown in the following illustration. Successive maps illustrate population growth by changing the color of each county as the population of that county changes over time.
The GIFANIM device driver does not provide a pull-down menu or other interactive controls, but it does provide a simple means of translating multiple SAS/GRAPH images into a single automated loop. The resulting GIF output is easily displayed in your own HTML files.
To change the amount of time that each image is displayed, you can change the value of the DELAY= goption.
The SAS code for this example is in the SAS Sample Library and is named GWBANIMA.
/** Designate a GIF file for the GMAP output. **/ filename animmap ' your_web_path/your_gif.gif '; /** Designate an HTML output file. Use the path **/ /** name that you specified for animmap. **/ filename htmlfile ' your_web_path/your_htm.htm '; /** Define a macro variable that points to the **/ /** GMAP output. Use the path and file names **/ /** names that you specified for animmap. No **/ /** quotes are needed here. **/ %let mapsrc= your_web_path/your_gif.gif ; goptions reset=all dev=gifanim gsfmode=replace gsfname=animmap xpixels=792 ypixels=600 transparency iteration=0 delay=150 disposal=background ftext='Swiss' htext=1.5; /* Create the HTML file that will display the */ /* GIF animation. */ data _null_; file htmlfile; source=quote("&mapsrc"); put '<HTML>'; put '<BODY>'; put '<BLOCKQUOTE>'; put '<img src=' source ' alt="NC Population Growth"' ' width="792" height="600"></P>'; put '</BLOCKQUOTE>'; put '</BODY>'; put '</HTML>'; /** Generate the data for the PROC GMAP **/ /** statements. **/ data NCPop; length Name $ 32; input State County P1990 P1980 P1970 P1960 P1950 / P1940 P1930 P1920 P1910 P1900 / AreaLand AreaWater / X Y / Name &; SquareMiles = AreaLand * 0.000386102158496; Pop1900 = P1900 / SquareMiles; Pop1910 = P1910 / SquareMiles; Pop1920 = P1920 / SquareMiles; Pop1930 = P1930 / SquareMiles; Pop1940 = P1940 / SquareMiles; Pop1950 = P1950 / SquareMiles; Pop1960 = P1960 / SquareMiles; Pop1970 = P1970 / SquareMiles; Pop1980 = P1980 / SquareMiles; Pop1990 = P1990 / SquareMiles; label Pop1900 = '1900 Population Per Square Mile' Pop1910 = '1910 Population Per Square Mile' Pop1920 = '1920 Population Per Square Mile' Pop1930 = '1930 Population Per Square Mile' Pop1940 = '1940 Population Per Square Mile' Pop1950 = '1950 Population Per Square Mile' Pop1960 = '1960 Population Per Square Mile' Pop1970 = '1970 Population Per Square Mile' Pop1980 = '1980 Population Per Square Mile' Pop1990 = '1990 Population Per Square Mile'; format P1990 P1980 P1970 P1960 P1950 P1940 P1930 P1920 P1910 P1900 comma8.; label P1990 = '1990 Population' P1980 = '1980 population' P1970 = '1970 Population' P1960 = '1960 Population' P1950 = '1950 Population' P1940 = '1940 Population' P1930 = '1930 Population' P1920 = '1920 Population' P1910 = '1910 Population' P1900 = '1900 Population'; datalines; 37 1 108213 99319 96362 85674 71220 57427 42140 32718 28712 25665 1115485 10649 -79.398440 36.043667 Alamance County 37 3 27544 24999 19466 15625 14554 13454 12922 12212 11592 10960 674244 7682 -81.176957 35.921840 Alexander County /** See sample GWBANGIF for the full data set. **/ 37 199 15419 14934 12629 14008 16306 17202 14486 15093 12072 11464 809243 1752 -82.310012 35.902682 Yancey County ; run; /** Extract the NC data from the Counties map **/ /** data in the MAPS library. **/ data NCC; set Maps.Counties; where State = 37 and Density <= 3; run; proc gproject data=NCC out=NCCounty; id State County; run; /** Produce a color ramp in temp.sas and use **/ /** the file to generate PATTERN statements. **/ data _null_; file 'temp.sas'; r = 224; rinc = -r/100; g = 176; ginc = -g/100; b = 160; binc = -b/100; do i=1to99; put 'pattern' i ' v=s c=cx' r hex2. g hex2. b hex2. ';'; r + rinc; g + ginc; b + binc; end; run; %inc 'temp.sas'; /** Create an Annotate data set to **/ /** produce a legend for the map. **/ data a; length color function style $ 8 text $ 20; retain xsys ysys '3' when 'A' style 'S'; r = 224; rinc = -r/100; g = 176; ginc = -g/100; b = 160; binc = -b/100; x = 25; xinc = 0.5; do i = 1 to 99; color = 'cx' put(r, hex2.) put(g, hex2.) put(b, hex2.); function = 'MOVE'; y=5; output; function = 'BAR'; x + xinc; y = 10; output; r + rinc; g + ginc; b + binc; end; function = 'LABEL'; Style = "'Swiss'"; Text = '800 people/square mile'; Position = '6'; x + xinc; y = 7.5; output; Text = '1'; Position = '4'; x = 24.5; y = 7.5; output; run; /* Set the title, footnote, and legend. */ title f='Swiss' h=2 'North Carolina Population 1900-1990'; footnote 'Source: US Census Bureau'; legend1 frame label=(position=(top center)); /** Generate the multiple images that **/ /** make up the GIF animation. **/ proc gmap map=NCCounty data=NCPop anno=a; id State County; title2 f='Swiss' h=3 '1900'; choro Pop1900 / midpoints=8 to 792 by 8 coutline=black nolegend; run; /* Suppress header information and begin */ /* appending additional images. */ goption gsfmode=append; title2 f='Swiss' h=3 1910'; choro Pop1910 / midpoints=8 to 792 by 8 coutline=black nolegend; run; title2 f='Swiss' h=3 '1920'; choro Pop1920 / midpoints=8 to 792 by 8 coutline=black nolegend; run; title2 f='Swiss' h=3 '1930'; choro Pop1930 / midpoints=8 to 792 by 8 coutline=black nolegend; run; title2 f='Swiss' h=3 '1940'; choro Pop1940 / midpoints=8 to 792 by 8 coutline=black nolegend; run; title2 f='Swiss' h=3 '1950'; choro Pop1950 / midpoints=8 to 792 by 8 coutline=black nolegend; run; title2 f='Swiss' h=3 '1960'; choro Pop1960 / midpoints=8 to 792 by 8 coutline=black nolegend; run; title2 f='Swiss' h=3 '1970'; choro Pop1970 / midpoints=8 to 792 by 8 coutline=black nolegend; run; title2 f='Swiss' h=3 '1980'; choro Pop1980 / midpoints=8 to 792 by 8 coutline=black nolegend; run; /* Mark the end of the animation by */ /* appending a GIF trailer to the data */ /* stream. */ goptions gepilog='3B'x; /* Generate the final image. */ title2 f='Swiss' h=3 '1990'; choro Pop1990 / midpoints=8 to 792 by 8 coutline=black nolegend; run; quit;