BookmarkSubscribeRSS Feed
tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

HappyAnalogNewYear.gif

 

ODS Graphics take on a brewpub's NYE party invite. Happy New Year, all!

 

* Fun w/SAS ODS Graphics: New Year's Eve Analog Watch Countdown;
 
data clock1;                                           * Generate points for clock seconds (text plot - filled circles);
pi=constant('pi');
do remaining=0 to 10;                                  * Generate one "frame" for each countdown second;
do seconds=0 to 59;  
  tick=.;
  xTxt=cos(seconds/60*2*pi);                           * Second markers aranged around circle of radius=1;                           
  yTxt=sin(seconds/60*2*pi);                              
  if mod(seconds,5) then output;                       * Every 5th second is plotted as a bar (see next step);
end;
end;

data clock2;                                           * Generate points for clock seconds (vector plot line segments);
pi=constant('pi');
do remaining=0 to 10;                                  * Generate one "frame" for each countdown second;
do seconds=0 to 55 by 5;                               * Every 5th second is plotted as a bar instead of circle;
  vX1=.925*cos(seconds/60*2*pi);                       * Line segments extend beyond seconds markers;                              
  vX2=1.075*cos(seconds/60*2*pi);                               
  vY1=.925*sin(seconds/60*2*pi);                               
  vY2=1.075*sin(seconds/60*2*pi);                          
  output;
end;
end;

data clock3;                                           * Generate points for clock seconds hand (vector plot line);
pi=constant('pi');
do seconds=50 to 60;                                   * Generate one "frame" for each countdown second;  
  remaining=60-seconds; 
  vXsec=1.075*sin(seconds/60*2*pi);                    * Seconds hand extends to length of bars;                             
  vYsec=1.075*cos(seconds/60*2*pi);                               
  output;
end;

data clock4;                                           * Generate points for clock minute hand (vector plot line);
pi=constant('pi');                                    
do seconds=50 to 60;                                   * Generate one "frame" for each countdown second;
  remaining=60-seconds;
  vXmin=1.075*sin((59*60+seconds)/(60*60)*2*pi);       * Minutes hand extends to length of bars;          
  vYmin=1.075*cos((59*60+seconds)/(60*60)*2*pi);                               
  output;
end;
run;

data clock5;                                           * Generate points for clock hour hand (vector plot line);
pi=constant('pi');                                    
do seconds=50 to 60;                                   * Generate one "frame" for each countdown second;
  remaining=60-seconds;                                * Hours hand is shorter than seconds/minutes hands;
  vXhr=.7*sin((11*60*60+59*60+seconds)/(12*60*60)*2*pi);            
  vYhr=.7*cos((11*60*60+59*60+seconds)/(12*60*60)*2*pi);                               
  output;
end;
run;

data clock6;                                           * Generate countdown text, points (text plot);
do remaining=10 to 1 by -1;                            * Generate one "frame" for each countdown second;
  text=compress(put(remaining,2.));
  txtX=0; txtY=0;
  output;
end;  

data clock7;                                           * Generate "Happy New Year" text, point (text plot);
remaining=0;                                           * Last frame;
text2="Happy*New Year!*2018"; 
txt2X=0; txt2Y=0; 

data clock;                                            * Merge chart datasets;
set clock1 clock2 clock3 clock4 clock5 clock6 clock7;

proc sort data=clock;                                  * Sort by countdown (desc seconds remaining);
by descending remaining;

proc format;                                           * Unicode filled circle character for circles on clock;
value tickfmt other="(*ESC*){unicode '25CF'x}";

proc template;                                         * Create animated GIF "clock" with countdown;
define statgraph newyearplot;
begingraph / opaque=true border=false drawspace=layoutpercent backgroundcolor=black;
layout overlayequated / equatetype=square border=false  
       WALLDISPLAY=NONE commonaxisopts=(viewmin=-1.15 viewmax=1.15 tickvaluelist=(-1.15 1.15)) 
       xaxisopts=(display=none OFFSETMAX=0 OFFSETMIN=0) yaxisopts=(display=none OFFSETMAX=0 OFFSETMIN=0);
/* Countdown text (10.9.8.7.6.5.4.3.2.1) */
textplot x=txtX y=txtY text=text / position=center vcenter=bbox splitchar='*' contributeoffsets=none
                                   textattrs=(size=216pt weight=bold color=silver) strip=true;
/* Watch dial seconds markers (cirlces) */
textplot x=xTxt y=yTxt text=tick / position=center vcenter=bbox strip=true contributeoffsets=none
                                   textattrs=(size=18pt weight=bold color=silver);    
/* Watch dial seconds markers (every 5th marker is a bar) */
vectorplot xorigin=vX1 x=vX2 yorigin=vY1 y=vY2 / lineattrs=(thickness=7pt color=silver)arrowheads=false;  
/* Seconds hand */    
vectorplot xorigin=0 x=vXsec yorigin=0 y=vYsec / lineattrs=(thickness=3pt color=white) arrowheads=false; 
/* Minutes hand */    
vectorplot xorigin=0 x=vXmin yorigin=0 y=vYmin / lineattrs=(thickness=4pt color=white) arrowheads=false;      
/* Hours hand */    
vectorplot xorigin=0 x=vXhr yorigin=0 y=vYhr / lineattrs=(thickness=9pt color=white) arrowheads=false;      
/* Center of watch dial (white circle) */    
ellipseparm xorigin=0 yorigin=0 semimajor=.07 semiminor=.07 slope=0 / display=(fill outline) fillattrs=(color=white) outlineattrs=(color=black);
/* Center of watch dial (black dot) */    
ellipseparm xorigin=0 yorigin=0 semimajor=.03 semiminor=.03 slope=0 / display=(fill outline) fillattrs=(color=black) outlineattrs=(color=black);
/* Happy New Year! 2018 greeting */    
textplot x=txt2X y=txt2Y text=text2 / position=center vcenter=bbox splitchar='*' splitpolicy=splitalways backlight=1
                                      textattrs=(size=50pt weight=bold color=silver) contributeoffsets=none strip=true;
endlayout; 
endgraph;
end;

options nobyline;                                      * Animated GIF initialization;
ods _all_ close;
options papersize=('5 in', '5 in') printerpath=gif animation=start 
        nodate nonumber animloop=YES animduration=1 NOANIMOVERLAY ;
ods printer file='/folders/myfolders/HappyAnalogNewYear/HappyAnalogNewYear.gif';
ods graphics / width=5in height=5in imagefmt=GIF border=off;
                                                       * Generate 10-9-8-7-6-5-4-3-2-1 countdown frames;
proc sgrender data=clock(where=(remaining>0)) template=newyearplot; 
by descending remaining;
format tick tickfmt.;
run;                                                   * Generate Happy New Year! 2018 frame;
options animduration=5;                                * Freeze last frame for 5 seconds;
proc sgrender data=clock(where=(remaining=0)) template=newyearplot; 
format tick tickfmt.;

options printerpath=gif animation=stop;                * Wrap-up animated GIF creation;                         
run;
ods printer close;
2 REPLIES 2
ChrisHemedinger
Community Manager

I love it!  Just enough geometry at work to provide a math nerd fix.

 

Sorry I didn't see this before New Year's Eve - I would have projected it during our gathering as midnight approached.  

Check out SAS Innovate on-demand content! Watch the main stage sessions, keynotes, and over 20 technical breakout sessions!
jgcasatejada
Calcite | Level 5
Its wonderfull

With SAS , can you do anything???

Thanks to open my eyes

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 2 replies
  • 4189 views
  • 6 likes
  • 3 in conversation