info343/lectures/special-effects/index.shtml

<!--#include virtual="../s5/commontop.html" -->
      <title>Lecture 8: Special effects: jQuery effects, CSS3 Transforms &amp; Transitions — INFO 343 Autumn 2012</title>
   </head>

   <body>
      <div class="layout">
         <div id="controls"><!-- DO NOT EDIT --></div>
         <div id="currentSlide"><!-- DO NOT EDIT --></div>
         <div id="header"></div>
         <div id="footer">
            <h1>INFO 343 Lecture 8</h1>
            <h2>Special effects: jQuery effects, CSS3 Transforms &amp; Transitions</h2>
         </div>
      </div>

      <div class="presentation">
         <div class="slide">
            <h1>Special effects: jQuery effects, CSS3 Transforms &amp; Transitions</h1>
            <h3>Lecture 8</h3>
            <h4>
               Suggested Reading: <br/>
               <a href="http://css3.bradshawenterprises.com/"><cite>Using CSS3 Transitions, Transforms, and Animation</cite></a> by Rich Bradshaw
            </h4>

            <p class="license">
               © 2011–12 Morgan Doocy
            </p>

            <div class="w3c">
               <a href="http://validator.w3.org/check/referer"><img src="../s5/images/w3c-xhtml11.png" alt="Valid XHTML 1.1" /></a>
               <a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="../s5/images/w3c-css.png" alt="Valid CSS!" /></a>
            </div>
         </div>
         
         
         <div class="slide">
            <h1>Foreach-style looping: <code>.each()</code></h1>
<pre class="syntaxtemplate js">
<var>$jQueryObj</var><em>.each</em>(<var>function</var>)

function <var>function</var>(<var>index</var>, <var>element</var>) {
   ...
}
</pre>

<pre class="examplecode js">
$('.rectangle')<em>.each</em>(function(<em>i, elem</em>) {
   <span class="comment">// i is 0-based index; elem is the DOM object</span>
   <em>$(elem)</em>.text("This is rectangle number " + (i + 1));
});
</pre>
            <ul>
               <li>Iterate over jQuery search results</li>
               <li>Callback function is called each time, passed index and element
                  <ul>
                     <li>In callback, can also refer to element with <code>this</code> instead</li>
                  </ul>
               </li>
            </ul>
         </div>
         
         
         <div class="slide">
            <h1>Foreach for standard lists: <code>$.each()</code></h1>
<pre class="syntaxtemplate js">
<em>$.each</em>(<var>enumerable</var>, <var>function</var>)

function <var>function</var>(<var>key</var>, <var>value</var>) {
   ...
}
</pre>

<pre class="examplecode js">
var <em>words</em> = {
   'flammable': 'inflammable',
   'duh': 'no duh'
}
<em>$.each</em>(<em>words</em>, function(<em>key</em>, <em>val</em>) {
   alert(key + ': ' + val);
});

<span class="comment">// 'flammable: inflammable'</span>
<span class="comment">// 'duh: no duh'</span>
</pre>
            <ul>
               <li>Slightly different function, takes a standard JavaScript array or object as its first parameter</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>jQuery efficiency</h1>
            
<pre class="examplecode js">
<del><em>$('.foo')</em>.css('font-size', '200%');
<em>$('.foo')</em>.css('color', 'red');
<em>$('.foo')</em>.css('background-color', 'yellow');</del>

<em>var $foo = $('.foo');</em>
<em>$foo</em>.css('font-size', '200%');
<em>$foo</em>.css('color', 'red');
<em>$foo</em>.css('background-color', 'yellow');
</pre>
            
            <ul>
               <li>Each time you use <code>$()</code> you’re searching the entire DOM again(!)</li>
               <li>To perform several operations on the same set of elements, <strong>save and reuse the set</strong></li>
            </ul>
         </div>
         
         
         
         <div class="slide titleslide">
            <h1>Special Effects</h1>
            
            <ol>
               <li><strong>jQuery Visual Effects</strong></li>
               <li>CSS3 Transforms</li>
               <li>CSS3 Transitions</li>
            </ol>
         </div>
         
         
         
         <div class="slide">
            <h1>
               Core jQuery visual effects
            </h1>
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
            <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/jquery-ui.min.js"></script>
            <style type="text/css">
               .effectslist dt {
                  float: left;
                  width: 7em;
               }
               .effectslist dd {
                  margin-left: 7em;
               }
            </style>
            
            <div class="demo" style="margin: 1em 50px; width:120px; height:120px; font-size: 16pt; float: left">
               <div class="example" id="demo-core" style="background-color: yellow;">
                  <div style="height: 120px; text-align: center">
                     <span>Click →<br/> to show or hide me using effects</span>
                  </div>
               </div>
            </div>
            
            <dl class="effectslist" style="margin-left: 250px">
               <dt>Disappearing:</dt>
               <dd>
                  <button class="effectbutton" onclick="$('#demo-core').hide(1000);">hide</button>
                  <button class="effectbutton" onclick="$('#demo-core').fadeOut(1000);">fadeOut</button>
                  <button class="effectbutton" onclick="$('#demo-core').slideUp(1000);">slideUp</button>
               </dd>
               
               <dt>Appearing:</dt>
               <dd>
                  <button class="effectbutton" onclick="$('#demo-core').show(1000);">show</button>
                  <button class="effectbutton" onclick="$('#demo-core').fadeIn(1000);">fadeIn</button>
                  <button class="effectbutton" onclick="$('#demo-core').slideDown(1000);">slideDown</button>
               </dd>
               
               <dt>Toggling:</dt>
               <dd>
                  <button class="effectbutton" onclick="$('#demo-core').toggle(1000);">toggle</button>
                  <button class="effectbutton" onclick="$('#demo-core').fadeToggle(1000);">fadeToggle</button>
                  <button class="effectbutton" onclick="$('#demo-core').slideToggle(1000);">slideToggle</button>
               </dd>
            </dl>
            
<pre class="examplecode js" style="clear: left">
$('#foo')<em>.toggleSlide()</em>;
$('#bar').fadeIn(<em>500</em>); <span class="comment">// .5 sec</span>
</pre>
            
            <ul>
               <li>Basic animations built into core jQuery (don’t need separate <span class="term">jQuery UI</span> library)</li>
               <li>Optional duration parameter in milliseconds, or <code>'slow'</code> (= 600 ms) / <code>'fast'</code> (= 200 ms). (Default <code>600</code> ms)
                  <ul>
                     <li>Without duration, <code>.hide()</code> sets element to <code>display: none</code>, and <code>.show()</code> restores <code>display</code> to its original value (e.g., <code>display: inline</code> for inline element)</li>
                     <li>With optional duration parameter, <code>.hide()</code> and <code>.show()</code> become animated</li>
                  </ul>
               </li>
            </ul>

         </div>
         
         
         
         <div class="slide">
            <h1>Options for core effects</h1>
            
<pre class="examplecode js">
<span class="comment">// "easing": manner in which animation should speed up or slow down over time</span>
$('#foo').show('slow', <em>'easeInOutCubic'</em>);

<span class="comment">// callback function: executed after the effect is done</span>
$('#foo').hide(9999999, 'easeOutBounce', <em>function() { alert("FINALLY, geez.") }</em>);

<span class="comment">// globally turns off ALL effects!</span>
jQuery.fx.off = true;
</pre>
            
            <ul>
               <li>Optional <span class="term">easing function</span> changes the "fluidity" of animation
                  <ul>
                     <li>Uses mathematical equation to dynamically adjust speed of animation</li>
                     <li><a href="http://api.jqueryui.com/easings/">Examples and full list of jQuery easings</a></li>
                  </ul>
               </li>
               <li>Optional <span class="term">callback function</span> gets executed after the effect has finished
                  <ul>
                     <li>Frequent use: <code>.remove()</code> the element from the DOM only after it’s completely hidden</li>
                  </ul>
               </li>
               <li>Set <code>jQuery.fx.off</code> global to completely turn off/on all effects</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Custom animations: <code><a href="http://api.jquery.com/animate/">.animate()</a></code></h1>
<pre class="examplecode js" onclick="custom_animate();" id="custom_animate_pre" style="position: relative; overflow: hidden">
$(this).<em>animate</em>({
   <span class="comment">// CSS properties to transition to</span>
   height: <em>'200px'</em>, <span class="comment">// make 50 pixels tall</span>
   left: <em>'+=100'</em>, <span class="comment">// special incrementor: move right 50 pixels every time</span>
   fontSize: <em>'300%'</em>, <span class="comment">// increase font size</span>
   opacity: <em>.5</em>
}, {
   <span class="comment">// effect options</span>
   duration: 1000,
   easing: 'linear',
   complete: function() { alert('Done!') },
   <em>step</em>: function(now, fx) { <span class="comment">// step function: executed every frame</span>
      console.log("now property '" + fx.prop + "' has the value '" + now + "'");
   },
   <em>specialEasing</em>: { <span class="comment">// special per-property easings</span>
      'height': 'easeInOutBounce',
      'fontSize': 'easeInQuint'
   }
});
</pre>
         <script type="text/javascript">
            function custom_animate() {
               $('#custom_animate_pre').animate({
                  'height': '200px',
                  'left': '+=100',
                  'fontSize': '300%',
                  'opacity': .5
               }, {
                  duration: 1000,
                  easing: 'linear',
                  complete: function() { alert('Done!') },
                  step: function(now, fx) {
                     console.log("now property '" + fx.prop + "' has the value '" + now + "'");
                  },
                  specialEasing: {
                     'left': 'easeInOutBounce',
                     'fontSize': 'easeInQuint'
                  }
               });
            }
         </script>
         </div>
         
         
         <div class="slide">
            <h1>Chaining and pausing effects</h1>
            
            <div class="demo" style="width: 750px; height: 150px; margin: 1em auto; border: solid 1px black; position: relative;">
               <img src="flash.jpg" style="width: 75px; border: dashed 2px red; position: absolute;" alt="The Flash" id="the-flash" />
            </div>
            
<pre class="examplecode js">
<span class="comment">// happens in sequence, not all at once:</span>
$('#the-flash').animate({ right: 0 }).animate({ bottom: 0 }).delay(500)
               .animate({ left: 0 }).animate({ top: 0 });
</pre>
            
            <script type="text/javascript">
               var started = false;
               var running = false;
               $('#the-flash').click(function() {
                  if (!started) {
                     $('#the-flash').animate({ right: 0 }).animate({ bottom: 0 }).delay(500).animate({ left: 0 }).animate({ top: 0 }, function() {
                        this.style.left = '';
                        this.style.top = '';
                        this.style.bottom = '';
                        this.style.right = '';
                        started = false;
                     });
                     started = true;
                     running = true;
                  } else if (!running) {
                     running = true;
                     $('#the-flash').dequeue();
                  } else {
                     running = false;
                     $(this).stop();
                  }
               });
            </script>
            
            <ul>
               <li>Chained effects are ALWAYS evaluated in sequence.
                  <ul>
                     <li>(No easy way to evaluate simultaneously without plugins)</li>
                  </ul>
               </li>
               <li>Can wait between effects with <code>.delay()</code></li>
               <li>Can stop an animation with <code>.stop()</code>; call the most recent effect again to restart</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Fancier effects in jQuery UI</h1>
            
            <style type="text/css">
               .jqueryui.effectslist dt {
                  width: 12em;
/*                  background-color: fuchsia;*/
                  margin-bottom: 1em;
               }
               .jqueryui.effectslist dd {
                  margin-left: 12em;
                  height: 1.25em;
/*                  background-color: blue;*/
                  margin-bottom: 1em;
               }
               .jqueryui.effectslist dd pre {
                  margin: 0;
/*                  height: 1.25em;*/
/*                  line-height: 1.25em;*/
               }
               .jqueryui.effectslist dd pre input,
               .jqueryui.effectslist dd pre select,
               .jqueryui.effectslist dd pre button {
                  font-size: 100%;
               }
               .ui-effects-transfer {
                  border: dashed 2px black;
                  z-index: 5;
               }
            </style>
            
            <div class="demo" style="margin: 1em 50px; width:120px; height:120px; font-size: 16pt; float: left">
               <div class="example" id="demo-jqueryui" style="background-color: lightblue;">
                  <div style="height: 120px; text-align: center">
                     <span>Click →<br/> to show or hide me using effects</span>
                  </div>
               </div>
            </div>
            
            <dl class="effectslist jqueryui" style="margin-left: 250px">
               <dt>Appearing &amp; disappearing:</dt>
               <dd><pre class="examplecode js">$('#foo').<em>toggle</em>('<select id="app_dis_effect"><option>blind</option><option>clip</option><option>drop</option><option>explode</option><option>fade</option><option>fold</option><option>puff</option><option>scale</option><option>size</option><option>slide</option></select>', <input type="text" size="3" id="app_dis_duration" value="1000" />); <button id="app_dis_doit" onclick="app_dis();">Do it!</pre></dd>
               
               <dt>Getting attention:</dt>
               <dd><pre class="examplecode js">$('#foo').<em>effect</em>('<select id="attention_effect"><option>bounce</option><option>highlight</option><option>pulsate</option><option>shake</option><option>transfer</option></select>', <input type="text" size="3" id="attention_duration" value="slow" />); <button id="attention_doit" onclick="attention();">Do it!</pre></pre></dd>
            </dl>
            
            <script type="text/javascript">
               function app_dis() {
                  var effect = $('#app_dis_effect').val();
                  var duration = $('#app_dis_duration').val();
                  if (parseInt(duration)) {
                     duration = parseInt(duration);
                  }
                  var options = {
                     'duration': duration
                  };
                  if (effect == 'drop' || effect == 'slide') {
                     options.direction = 'down';
                  } else if (effect == 'clip') {
                     options.direction = 'vertical';
                  } else if (effect == 'size') {
                     options.to = { height: 60, width: 200 };
                     options.origin = ['center', 'center'];
                     options.scale = 'box';
                  }
                  // alert(duration);
                  $('#demo-jqueryui').toggle(effect, options);
               }
               
               function attention() {
                  var effect = $('#attention_effect').val();
                  var duration = $('#attention_duration').val();
                  if (parseInt(duration)) {
                     duration = parseInt(duration);
                  }
                  var options = {
                     'duration': duration
                  };
                  if (effect == 'transfer') {
                     options.to = '#attention_doit';
                     // options.className = 'transfer';
                  }
                  $('#demo-jqueryui').effect(effect, options);
               }
            </script>
            
<pre class="examplecode js" style="clear: left">
&lt;script src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;<em>//ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/jquery-ui.min.js</em>&quot;&gt;&lt;/script&gt;
</pre>
            
            <ul>
               <li>Fancier effects come with separate <span class="term">jQuery UI</span> library</li>
               <li>Loaded in addition to core jQuery (must come after in code)</li>
               <li>Most effects have additional options
                  <ul>
                     <li>See <a href="http://api.jqueryui.com/category/effects/">Effects API</a> documentation</li>
                  </ul>
               </li>
            </ul>
            
            <!--
            clearQueue
            dequeue
            fadeTo
            queue
            -->
         </div>
         
         
         
         <div class="slide">
            <h1>Limitations of jQuery effects</h1>
            
            <ul>
               <li><strong>Incomplete</strong>
                  <ul>
                     <li>Can move (i.e., <em>translate</em>) elements</li>
                     <li>Can’t do other basic affine transformations:
                        <ul>
                           <li>Rotate, scale, reflect, shear/skew, 3-D perspective, etc.</li>
                        </ul>
                     </li>
                  </ul>
               </li>
               <li><strong>Inefficient</strong>
                  <ul>
                     <li>JavaScript is slower than native code
                        <ul>
                           <li>jQuery uses JavaScript timers to make small changes to CSS code every few milliseconds</li>
                        </ul>
                     </li>
                     <li>Graphics cards are built to do effects natively and efficiently
                        <ul>
                           <li>JavaScript code cannot take advantage of hardware acceleration</li>
                        </ul>
                     </li>
                  </ul>
               </li>
               <li class="incremental">Solution: CSS3 Transforms &amp; Transitions</li>
            </ul>
         </div>
         
         
         
         <div class="slide titleslide">
            <h1>Special Effects</h1>
            
            <ul>
               <li>Scriptaculous Visual Effects</li>
               <li><strong>CSS3 Transforms</strong></li>
               <li>CSS3 Transitions</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>CSS3 Special Effects</h1>
            
            <p>Upcoming CSS3 standard includes features for affine transformations and animation.</p>
            
            <ul>
               <li><strong>Transforms</strong>
                  <ul>
                     <li>Complete affine transformations: rotate, scale, reflect, skew</li>
                     <li>2– and 3–dimensional transformations</li>
                  </ul>
               </li>
               <li><strong>Transitions</strong>
                  <ul>
                     <li>Animation (“tweening”) between an initial and final state, triggered when state changes</li>
                  </ul>
               </li>
               <li><strong>Animations</strong>
                  <ul>
                     <li>More complex animations with more states, without needing to be triggered</li>
                     <li>Sometimes needed to do something transitions can’t</li>
                     <li>(We won’t cover animations here)</li>
                  </ul>
               </li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>CSS3 Transforms: The <code><a href="http://www.w3schools.com/cssref/css3_pr_transform.asp">transform</a></code> property</h1>
            
            <pre class="syntaxtemplate css" style="font-size: 90%"><var>selector</var> {
  -webkit-<em>transform</em>: <var>function1</var>, <var>function2</var>, ...;
  -moz-<em>transform</em>: <var>function1</var>, <var>function2</var>, ...;
  -ms-<em>transform</em>: <var>function1</var>, <var>function2</var>, ...;
  -o-<em>transform</em>: <var>function1</var>, <var>function2</var>, ...;
  <em>transform</em>: <var>function1</var>, <var>function2</var>, ...;
}</pre>
            
            <ul>
               <li><var>function</var>s cover most of the affine 2-D or 3-D transformations:
                  <ul>
                     <li><code>translate</code>, <code>rotate</code>, <code>scale</code>, <code>skew</code></li>
                     <li>(covers reflection via a 3D rotation effect)</li>
                  </ul>
               </li>
               <li>due to unfinished standard, basic <code>transform</code> property does not work in most browsers
                  <ul>
                     <li><strong>must specify custom properties with prefixes for each browser instead:</strong> <code>-webkit</code>, <code>-moz</code>, <code>-o</code>, <code>-ie</code></li>
                     <li><a href="http://prefixr.com/">Nifty time-saving tool</a></li>
                  </ul>
               </li>
            </ul>
         </div>
         
         
         <style type="text/css">
            .transform_container {
               position: relative;
               border: solid 2px blue;
               background-color: lightgray;
               float: right;
               width: 33%;
            }
            .original, .transformed {
               position: absolute;
               left: 0;
               background-color: red;
               width: 10em;
               height: 5em;
               border: solid 3px black;
               text-transform: uppercase;
               font-family: sans-serif;
            }
            .original {
               opacity: .5;
            }
            .transformed {
               opacity: .75;
            }
         </style>
         
         
         <div class="slide">
            <h1>Translation: The <code><a href="http://www.w3schools.com/css3/css3_2dtransforms.asp">translate</a></code> function</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-transform: <em>translate(</em><var>x-dimension</var>, <var>y-dimension</var><em>);</em>
}</pre>
            
            <pre class="examplecode css">#original, #transformed { position: absolute; left: 0; }
#transformed {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: <em>translate(50px, 25%)</em>;
}</pre>
            <style type="text/css">
               #translate_transformed {
                  -webkit-transform: translate(50px, 25%);
                  -moz-transform: translate(50px, 25%);
                  -ms-transform: translate(50px, 25%);
                  -o-transform: translate(50px, 25%);
                  transform: translate(50px, 25%);
               }
            </style>
            <div class="exampleoutput transform_container" style="height: 7.5em">
               <div class="transform_example original">Original</div>
               <div id="translate_transformed" class="transform_example transformed">Transformed</div>
            </div>
            
            <ul>
               <li>shifts the object by <var>x-dimension</var> and <var>y-dimension</var></li>
               <li>usual CSS dimension units: <code>pt</code>, <code>px</code>, <code>%</code>, <code>em</code>, <code>in</code>, etc.</li>
               <li>can be positive or negative</li>
               <li>roughly equivalent to <code>position: absolute;<br/>left: <var>x-dimension</var>; top: <var>y-dimension</var>;</code></li>
               <li><strong>MUST include all browser-prefixed properties to work</strong></li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Scaling: The <code><a href="http://www.w3schools.com/css3/css3_2dtransforms.asp">scale</a></code> function</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-transform: <em>scale(</em><var>x-factor</var>, <var>y-factor</var><em>);</em>
}</pre>
            
            <pre class="examplecode css">#transformed {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: <em>scale(.5, 1.25)</em>;
}</pre>
            <style type="text/css">
               #scale_transformed {
                  -webkit-transform: scale(.5, 1.25);
                  -moz-transform: scale(.5, 1.25);
                  -ms-transform: scale(.5, 1.25);
                  -o-transform: scale(.5, 1.25);
                  transform: scale(.5, 1.25);
               }
            </style>
            <div class="exampleoutput transform_container" style="height: 7.5em">
               <div class="transform_example original">Original</div>
               <div id="scale_transformed" class="transform_example transformed">Transformed</div>
            </div>
            
            <ul>
               <li>scales the object by <var>x-factor</var> along x-axis and <var>y-factor</var> along y-axis</li>
               <li>factor is decimal scalar, <code>1.0</code> = 100%, <code>0.5</code> = 50%, etc.</li>
               <li>scales borders and inner contents too!</li>
               <li>content still selectable!</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Rotation: The <code><a href="http://www.w3schools.com/css3/css3_2dtransforms.asp">rotate</a></code> function</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-transform: <em>rotate(</em><var>angle</var><em>);</em>
}</pre>
            
            <pre class="examplecode css">#transformed {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: <em>rotate(30deg)</em>;
}</pre>
            <style type="text/css">
               #rotate_transformed {
                  -webkit-transform: rotate(30deg);
                  -moz-transform: rotate(30deg);
                  -ms-transform: rotate(30deg);
                  -o-transform: rotate(30deg);
                  transform: rotate(30deg);
               }
            </style>
            <div class="exampleoutput transform_container" style="height: 7.5em">
               <div class="transform_example original">Original</div>
               <div id="rotate_transformed" class="transform_example transformed">Transformed</div>
            </div>
            
            <ul>
               <li>rotates the object by <var>angle</var> (can be negative)</li>
               <li>must include units of <code>deg</code>, <code>grad</code>, <code>rad</code>, or <code>turn</code></li>
               <li>content still selectable!</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Skew/shear: The <code><a href="http://www.w3schools.com/css3/css3_2dtransforms.asp">skew</a></code> function</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-transform: <em>skew(</em><var>x-angle</var>, <var>y-angle</var><em>);</em>
}</pre>
            
            <pre class="examplecode css">#transformed {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: <em>skew(-45deg, 10deg)</em>;
}</pre>
            <style type="text/css">
               #skew_transformed {
                  -webkit-transform: skew(-45deg, 10deg);
                  -moz-transform: skew(-45deg, 10deg);
                  -ms-transform: skew(-45deg, 10deg);
                  -o-transform: skew(-45deg, 10deg);
                  transform: skew(-45deg, 10deg);
               }
            </style>
            <div class="exampleoutput transform_container" style="height: 7.5em">
               <div class="transform_example original">Original</div>
               <div id="skew_transformed" class="transform_example transformed">Transformed</div>
            </div>
            
            <ul>
               <li>skews the object by <var>x-angle</var> along the x-axis, and by <var>y-angle</var> along the y-axis</li>
               <li>must include units of <code>deg</code>, <code>grad</code>, <code>rad</code>, or <code>turn</code></li>
               <li>skews borders and contents too!</li>
               <li>content still selectable!</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Moving the origin: <code><a href="http://www.w3schools.com/css3/css3_2dtransforms.asp">transform-origin</a></code></h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-<em>transform-origin:</em> <var>x-dimension</var> <var>y-dimension</var>;
}</pre>
            
            <pre class="examplecode css">#transformed {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  <em>transform-origin: left bottom</em>;
  transform: rotate(-75deg);
}</pre>
            <style type="text/css">
               #origin_transformed_moved,
               #origin_transformed_original {
                  -webkit-transform: rotate(-75deg);
                  -moz-transform: rotate(-75deg);
                  -ms-transform: rotate(-75deg);
                  -o-transform: rotate(-75deg);
                  transform: rotate(-75deg);
               }
               #origin_transformed_moved {
                  -webkit-transform-origin: left bottom;
                  -moz-transform-origin: left bottom;
                  -o-transform-origin: left bottom;
                  -ms-transform-origin: left bottom;
                  transform-origin: left bottom;
               }
            </style>
            <div class="exampleoutput transform_container" style="height: 7.5em">
               <div class="transform_example original">Original</div>
               <div id="origin_transformed_moved" class="transform_example transformed">Transformed<br/><small>origin: left bottom</small></div>
               <div id="origin_transformed_original" class="transform_example transformed" style="opacity: .5">Transformed<br/><small>origin: default<br/>(center center)</small></div>
            </div>
            
            <ul>
               <li>moves the origin (0,0) to a different location</li>
               <li>affects the way all <code>transform</code> functions are applied</li>
               <li>dimensions can be usual dimensions (<code>pt</code>, <code>px</code>, <code>%</code>, etc.) or a keyword: <code>left</code>/<code>center</code>/<code>right</code>, <code>top</code>/<code>center</code>/<code>bottom</code></li>
               <li>default: <code>50% 50%</code> (= <code>center center</code>)</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>3D Transforms</h1>
            
            <p>In recent &amp; upcoming browsers, can specify 3-dimensional transforms:</p>
            
            <ul>
               <li>rotation around X and Y axes (in addition to the usual 2D rotation, which is around the Z axis)</li>
               <li>translation and scale along Z-axis as well</li>
               <li>perspective distortion</li>
            </ul>
            
            <p>Interactive examples:</p>
            
            <ul>
               <li><a href="http://www.westciv.com/tools/3Dtransforms/index.html">WestCiv 3D Transforms</a></li>
               <li><a href="http://css3.bradshawenterprises.com/all/#how2transforms">How to Use Transforms</a> (see sections “3D Examples” and “A cube made with 3d transforms”)</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>3D Rotation: X and Y axes</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-transform: <em>rotateX(</em><var>angle</var><em>);</em>
  -<var>prefix</var>-transform: <em>rotateY(</em><var>angle</var><em>);</em>
}</pre>
            
            <pre class="examplecode css" style="float: left; width: 60%">#transformedX {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: <em>rotateX(30deg)</em>;
}
#transformedY {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: <em>rotateY(-45deg)</em>;
}</pre>
            <style type="text/css">
               #rotate3dX_transformed {
                  -webkit-transform: rotateX(60deg);
                  -moz-transform: rotateX(60deg);
                  -o-transform: rotateX(60deg);
                  -ms-transform: rotateX(60deg);
                  transform: rotateX(60deg);
               }

               #rotate3dY_transformed {
                  -webkit-transform: rotateY(-45deg);
                  -moz-transform: rotateY(-45deg);
                  -o-transform: rotateY(-45deg);
                  -ms-transform: rotateY(-45deg);
                  transform: rotateY(-45deg);
               }
               
               .container_3d {
                  -webkit-perspective: 800px;
                  -moz-perspective: 800px;
                  -ms-perspective: 800px;
                  -o-perspective: 800px;
                  perspective: 800px;
               }
            </style>
            <div class="exampleoutput transform_container container_3d" style="height: 7.5em;">
               <div class="transform_example original">Original</div>
               <div id="rotate3dX_transformed" class="transform_example transformed">Transformed X<br/><small>(X-axis)</small></div>
               <div id="rotate3dY_transformed" class="transform_example transformed">Transformed Y<br/><small>(Y-axis)</small></div>
            </div>
            
            <ul style="clear: both;">
               <li>rotates the object by <var>angle</var> (can be negative); include units of <code>deg</code>, <code>grad</code>, <code>rad</code>, or <code>turn</code></li>
               <li>notice the planes intersecting!</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>3D Translation &amp; Scale</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-transform: <em>translateZ(</em><var>dimension</var><em>);</em>
  -<var>prefix</var>-transform: <em>scaleZ(</em><var>factor</var><em>);</em>
}</pre>
            
            <pre class="examplecode css" style="float: left; width: 60%">#translatedZ {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: <em>translateZ(-5em)</em>;
}
#scaledZ {
<span class="comment">/* (browser-prefixed properties omitted) */</span>
  transform: rotateY(-45deg)
             <em>scaleZ(.1)</em> translateZ(100em);
}</pre>
            <style type="text/css">
               #translatedZ_transformed {
                  -webkit-transform: translateZ(-5em);
                  -moz-transform: translateZ(-5em);
                  -ms-transform: translateZ(-5em);
                  -o-transform: translateZ(-5em);
                  transform: translateZ(-5em);
               }
               #scaledZ_transformed {
                  -webkit-transform: rotateY(-45deg) scaleZ(.1) translateZ(100em);
                  -moz-transform: rotateY(-45deg) scaleZ(.1) translateZ(100em);
                  -ms-transform: rotateY(-45deg) scaleZ(.1) translateZ(100em);
                  -o-transform: rotateY(-45deg) scaleZ(.1) translateZ(100em);
                  transform: rotateY(-45deg) scaleZ(.1) translateZ(100em);
               }
            </style>
            <div class="exampleoutput transform_container container_3d" style="height: 7.5em;">
               <div class="transform_example original">Original</div>
               <div id="translatedZ_transformed" class="transform_example transformed">Translated Z</div>
               <div id="scaledZ_transformed" class="transform_example transformed">Scaled Z</div>
            </div>
            
            <ul style="clear: both;">
               <li><code>translateZ</code> alters “depth” or distance from viewer (distance from origin if rotated)</li>
               <li><code>scaleZ</code> primarily affects scale of <code>translateZ</code> dimensions (.1 × 100em = 10em)</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>3D Perspective Distortion</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-<em>perspective:</em> <var>pixels</var>;
}</pre>
            
            <pre class="examplecode css" style="float: left; width: 60%"><span class="comment">/* (browser-prefixed properties omitted) */</span>
#container {
  border: solid 2px blue;
  background-color: gray;
  <em>perspective:</em> <select id="perspective_select" style="font-size: 100%" onchange="perspectiveChange(this.value);"><option>none</option><option>50000px</option><option>2000px</option><option selected="selected">800px</option><option>200px</option></select>;
}
#transformed {
  transform: rotateY(-45deg) translateZ(-5em);
}</pre>
            <script type="text/javascript">
               function perspectiveChange(value) {
                  $('#perspective_transformed').parent().css({
                     'WebkitPerspective': value,
                     'MozPerspective': value,
                     'MsPerspective': value,
                     'OPerspective': value,
                     'perspective': value,
                  });
               }
            </script>
            <style type="text/css">
               #perspective_transformed {
                  -webkit-transform: rotateY(-45deg) translateZ(-5em);
                  -moz-transform: rotateY(-45deg) translateZ(-5em);
                  -o-transform: rotateY(-45deg) translateZ(-5em);
                  -ms-transform: rotateY(-45deg) translateZ(-5em);
                  transform: rotateY(-45deg) translateZ(-5em);
               }
            </style>
            <div class="exampleoutput transform_container container_3d" style="height: 7.5em;">
               <div class="transform_example original">Original</div>
               <div id="perspective_transformed" class="transform_example transformed">Transformed</div>
            </div>
            
            <ul style="clear: both;">
               <li>alters “camera distance” from object, which affects perception of depth</li>
               <li>affects the perspective of <strong>child elements only</strong>, so set this property on a <strong>parent</strong></li>
            </ul>
         </div>
         
         
         
         <div class="slide titleslide">
            <h1>Special Effects</h1>
            
            <ul>
               <li>Scriptaculous Visual Effects</li>
               <li>CSS3 Transforms</li>
               <li><strong>CSS3 Transitions</strong></li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>CSS3 Transitions: the <code><a href="http://www.w3schools.com/cssref/css3_pr_transition.asp">transition</a></code> property</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-<em>transition:</em> <var>property</var> <var>duration</var> <var>timing function</var> <var>delay</var>;
}</pre>
            
            <pre class="examplecode css" style="float: left; width: 60%"><span class="comment">/* (browser-prefixed properties omitted) */</span>
#transformed {
  transform: rotate(-45deg);
  <em>transition: transform 2s ease-in-out,
              background-color .5s ease 2s;</em>
}
#transformed:hover {
  font-size: 200%;
  <em>background-color: blue;
  transform: rotate(10deg) scale(1.5);</em>
}</pre>
            <style type="text/css">
               #transition_rotate {
                  -webkit-transform: rotate(-45deg);
                  -moz-transform: rotate(-45deg);
                  -ms-transform: rotate(-45deg);
                  -o-transform: rotate(-45deg);
                  transform: rotate(-45deg);
                  
                  -webkit-transition: -webkit-transform 2s ease-in-out, background-color .5s ease 2s;
                  -moz-transition: -moz-transform 2s ease-in-out, background-color .5s ease 2s;
                  -o-transition: -o-transform 2s ease-in-out, background-color .5s ease 2s;
                  -ms-transition: -ms-transform 2s ease-in-out, background-color .5s ease 2s;
                  transition: transform 2s ease-in-out, background-color .5s ease 2s;
               }
               #transition_rotate:hover {
                  font-size: 200%;
                  width: 5em;
                  height: 2.5em;
                  background-color: blue;
                  
                  -webkit-transform: rotate(10deg) scale(1.5);
                  -moz-transform: rotate(10deg) scale(1.5);
                  -ms-transform: rotate(10deg) scale(1.5);
                  -o-transform: rotate(10deg) scale(1.5);
                  transform: rotate(10deg) scale(1.5);
               }
            </style>
            <div class="exampleoutput transform_container" style="height: 7.5em;">
               <div class="transform_example original">Original</div>
               <div id="transition_rotate" class="transform_example transformed">Transformed<br/><small>(hover over me!)</small></div>
            </div>
            
            <ul style="clear: both;">
               <li>Whenever the specified properties change, they’ll be animated.</li>
               <li>Can specify multiple properties, separated by comma.
                  <ul>
                     <li><strong>ONLY</strong> specified properties will be animated (e.g., <code>font-size</code> is not animated above)</li>
                  </ul>
               </li>
            </ul>
         </div>
         
         
            
         <div class="slide">
            <h1>Transition Timing Functions</h1>
            
            <p>The <var>timing function</var> specifies how the transition will speed up and slow down across its lifecycle.</p>
            
            <table class="standard">
               <tr>
                  <th>timing function</th>
                  <th>description</th>
               </tr>

               <tr>
                  <td><code>ease</code> (default)</td>
                  <td>quick start, gradual finish</td>
               </tr>
               <tr>
                  <td><code>ease-in</code></td>
                  <td>slow start, steady build to max speed</td>
               </tr>
               <tr>
                  <td><code>ease-out</code></td>
                  <td>start at max speed, steady slow to finish</td>
               </tr>
               <tr>
                  <td><code>ease-in-out</code></td>
                  <td>slow start, increase to max speed, slow to finish</td>
               </tr>
               <tr>
                  <td><code>linear</code></td>
                  <td>constant speed for entire duration</td>
               </tr>
               <tr>
                  <td><code>cubic-bezier(<var>n</var>, <var>n</var>, <var>n</var>, <var>n</var>)</code></td>
                  <td>specify your own <a href="http://matthewlein.com/ceaser/">custom B&eacute;zier curve function</a></td>
               </tr>
            </table>
         </div>
         
         
         <div class="slide">
            <h1>Where to specify transitions?</h1>
            <style type="text/css">
               #transitions_example {
                  width: 5em;
                  height: 5em;
                  background-color: red;
                  border: solid 1px black;
                  position: absolute;
                  left: 50%;
                  top: 50%;
                  margin-left: -2.5em;
                  margin-top: -2.5em;
                  line-height: 5em;
                  text-align: center;
                  -webkit-transition: width 1s ease, height 1s ease, font-size 1s ease, margin-left 1s ease, margin-top 1s ease, line-height 1s ease;
                  -moz-transition: width 1s ease, height 1s ease, font-size 1s ease, margin-left 1s ease, margin-top 1s ease, line-height 1s ease;
                  -o-transition: width 1s ease, height 1s ease, font-size 1s ease, margin-left 1s ease, margin-top 1s ease, line-height 1s ease;
                  -ms-transition: width 1s ease, height 1s ease, font-size 1s ease, margin-left 1s ease, margin-top 1s ease, line-height 1s ease;
                  transition: width 1s ease, height 1s ease, font-size 1s ease, margin-left 1s ease, margin-top 1s ease, line-height 1s ease;
               }
               .enlarged {
                  width: 7.5em;
                  height: 7.5em;
                  font-size: 1.5em;
                  margin-left: -3.75em;
                  margin-top: -3.75em;
                  line-height: 7.5em;
               }
            </style>
<div style="float: right; width: 30%; position: relative; height: 10em">
<div id="transitions_example">Click me!</div>
</div>
<script type="text/javascript">
   $('#transitions_example').click(function() {
      $(this).addClass('enlarged');
   });
</script>
<div class="example" style="width: 68%">
<pre class="examplecode css">
#foo {
   width: 5em; height: 5em;
   <em>transition: width 1s ease, height 1s ease,
               font-size 1s ease;</em>
}
.enlarged {
   <em>width: 7.5em; height: 7.5em;
   font-size: 1.5em;</em>
}
</pre>
<pre class="examplecode js">
$(document).ready(function() {
   $('#foo').click(function() {
      <em>$(this).addClass('enlarged');</em>
   });
});
</pre>
</div>
            
            <ul>
               <li>
                  Specify transitions on the <em>element whose properties will eventually change.</em>
                  <ul>
                     <li>Says, “When these properties of mine change, animate the transition.”</li>
                     <li>In this example, adding the class changes the specified properties, so the transition is animated.</li>
                  </ul>
               </li>
            </ul>
         </div>
         
         
         <div class="slide">
            <h1>Other transition options</h1>
            <style type="text/css">
               #transitions_options_container {
                  float: right;
                  width: 25%;
                  position: relative;
                  text-align: center;
                  -webkit-perspective: 500px;
                  -moz-perspective: 500px;
                  -ms-perspective: 500px;
                  -o-perspective: 500px;
                  perspective: 500px;
               }
               .transitions_options_example {
                  width: 5em;
                  height: 5em;
                  background-color: red;
                  border: solid 1px black;
                  display: inline-block;
                  margin: 1em;
/*                  line-height: 5em;*/
                  text-align: center;
                  -webkit-transition: -webkit-transform 1s ease;
                  transition: transform 1s ease;
                  
                  -webkit-transform-style: preserve-3d;
                  -moz-transform-style: preserve-3d;
                  -ms-transform-style: preserve-3d;
                  transform-style: preserve-3d;
               }
               #transitions_options_example_b {
                  -webkit-backface-visibility: hidden;
                  -moz-backface-visibility: hidden;
                  -ms-backface-visibility: hidden;
                  -o-backface-visibility: hidden;
                  backface-visibility: hidden;
               }

               #transitions_options_example_a {
                  -webkit-backface-visibility: visible;
                  -moz-backface-visibility: visible;
                  -ms-backface-visibility: visible;
                  -o-backface-visibility: visible;
                  backface-visibility: visible;
               }

               .transitions_options_example:hover {
                  -webkit-transform: rotateY(-135deg);
                  -moz-transform: rotateY(-135deg);
                  -o-transform: rotateY(-135deg);
                  -ms-transform: rotateY(-135deg);
                  transform: rotateY(-135deg);
               }
               #transitions_options_transform_style {
                  width: 100%;
                  font-size: 50%;
                  background-color: yellow;
                  -webkit-transform: rotateY(60deg);
                  -moz-transform: rotateY(60deg);
                  -o-transform: rotateY(60deg);
                  -ms-transform: rotateY(60deg);
                  transform: rotateY(60deg);
/*                  transform-origin: center center;*/
               }
            </style>

<div id="transitions_options_container">
<div id="transitions_options_example_a" class="transitions_options_example">
   I remain visible from behind
   <div id="transitions_options_transform_style">I’m rotated 60° from this element — change <code>transform-style</code></div>
</div>
<div id="transitions_options_example_b" class="transitions_options_example">I disappear past 90° (back not visible)</div>
</div>

<div class="example" style="width: 73%">
<pre class="examplecode css">
#foo, #bar {
   transition: transform 1s ease;
   <em>transform-style: <select id="transform-style" onchange="transformStyleUpdate();" style="font-size: 100%;"><option>preserve-3d</option><option>flat</option></select></em>;
}
#foo:hover, #bar:hover {
   transform: rotateY(-135deg);
}
#bar {
   <em>backface-visibility: hidden;</em>
}
</pre>
</div>

<script type="text/javascript">
   $('.transitions_options_example').click(function() {
      $(this).addClass('flipped');
   });
   function transformStyleUpdate() {
      var val = $('#transform-style').val();
      $('.transitions_options_example').css({
         'transform-style': val,
         '-webkit-transform-style': val,
         '-moz-transform-style': val,
         '-ms-transform-style': val,
         '-o-transform-style': val
      });
   }
</script>
            
            <ul>
               <li><code>transform-style</code> changes whether children are rendered in 2D or 3D
                  <ul>
                     <li><a href="http://www.w3schools.com/cssref/trycss3_transform-style_inuse.htm">Another demo of this</a> (Safari/Chrome only, due to next-generation “slider” control)</li>
                  </ul>
               </li>
               <li><code>backface-visibility</code> changes whether an element is visible from behind</li>
               <li><strong>Both of these</strong> must also be browser-prefixed
                  <ul>
                     <li><strong>BUG:</strong> <a href="http://prefixr.com/">Prefixr</a> doesn’t browser-prefix <code>backface-visibility</code>, but it needs to be.</li>
                  </ul>
               </li>
            </ul>
            
         </div>
         
         
         <div class="slide">
            <h1>Proper browser-prefixing</h1>

<div class="example" style="float: left; width: 60%">
<pre class="examplecode css">
#foo {
   <em>-webkit-transition</em>: <em>-webkit-transform</em> 1s ease;
   <em>-moz-transition</em>: <em>-moz-transform</em> 1s ease;
   <em>-ms-transition</em>: <em>-ms-transform</em> 1s ease;
   <em>-o-transition</em>: <em>-o-transform</em> 1s ease;
   <em>transition</em>: <em>transform</em> 1s ease;
}

#foo.altered {
   <em>-webkit-transform</em>: rotate(-45deg);
   <em>-moz-transform</em>: rotate(-45deg);
   <em>-ms-transform</em>: rotate(-45deg);
   <em>-o-transform</em>: rotate(-45deg);
   <em>transform</em>: rotate(-45deg);
}
</pre>
<pre class="examplecode js">
$('#foo').parent().css({
   '<em>-webkit-perspective</em>': '600px',
   '<em>-moz-perspective</em>': '600px',
   '<em>-ms-perspective</em>': '600px',
   '<em>-o-perspective</em>': '600px',
   '<em>perspective</em>': '600px'
});
</pre>
</div>
            
            <ul style="width: 35%; margin-left: 65%">
               <li>Browser-prefixing of <code>transform</code> inside <code>transition</code> must match that of <code>transition</code>.</li>
               <li>When setting styles in JavaScript, don’t forget to set browser-prefixed properties!</li>
            </ul>
         </div>
         
         
         <!-- <div class="slide">
            <h1>Specifying a different transition for each property</h1>
            
            <pre class="syntaxtemplate css"><var>selector</var> {
  -<var>prefix</var>-<em>transition-property:</em> <var>property1</var>, <var>property2</var>, ..., <var>propertyN</var>;
  -<var>prefix</var>-<em>transition-duration:</em> <var>duration1</var>, <var>duration2</var>, ..., <var>durationN</var>;
  -<var>prefix</var>-<em>transition-timing-function:</em> <var>function1</var>, <var>function2</var>, ..., <var>functionN</var>;
  -<var>prefix</var>-<em>transition-delay:</em> <var>delay1</var>, <var>delay2</var>, ..., <var>delayN</var>;
}</pre>
            
            <pre class="examplecode css" style="float: left; width: 60%"><span class="comment">/* (browser-prefixed properties omitted) */</span>
#container {
  border: solid 2px blue;
  background-color: gray;
  <em>perspective:</em> <select id="perspective_select" style="font-size: 100%" onchange="perspectiveChange(this.value);"><option>none</option><option>50000</option><option>2000</option><option selected="selected">800</option><option>200</option></select>;
}
#transformed {
  transform: rotateY(-45deg) translateZ(-5em);
}</pre>
            <script type="text/javascript">
               function perspectiveChange(value) {
                  $('perspective_transformed').parentNode.style.WebkitPerspective = value;
               }
            </script>
            <style type="text/css">
               #perspective_transformed {
                  -webkit-transform: rotateY(-45deg) translateZ(-5em);
                  -moz-transform: translateZ(-5em);
                  -ms-transform: translateZ(-5em);
                  -o-transform: translateZ(-5em);
                  transform: translateZ(-5em);
               }
            </style>
            <div class="exampleoutput transform_container" style="height: 7.5em; -webkit-perspective: 800">
               <div class="transform_example original">Original</div>
               <div id="perspective_transformed" class="transform_example transformed">Transformed</div>
            </div>
            
            <ul style="clear: both;">
               <li>each property can have its own timing, duration, etc.</li>
               <li>specifies that <var>property1</var> should use <var>function1</var> spread across <var>duration1</var> seconds, and so on</li>
            </ul>
         </div> -->
         
         
         
         <!-- <div class="slide">
            <h1></h1>
         </div> -->
         
         
         

<!--#include virtual="../s5/commonbottom.html" -->