<!--#include virtual="../s5/commontop.html" -->
<title>Lecture 8: Special effects: jQuery effects, CSS3 Transforms & 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 & Transitions</h2>
</div>
</div>
<div class="presentation">
<div class="slide">
<h1>Special effects: jQuery effects, CSS3 Transforms & 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 & 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">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="<em>//ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/jquery-ui.min.js</em>"></script>
</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 & 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 & 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 & 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é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" -->