├── README ├── styles.css ├── index.html └── impress.js /README: -------------------------------------------------------------------------------- 1 | This project contains the source files for the impress.js tutorial available here: 2 | http://www.cubewebsites.com/blog/guides/how-to-use-impress-js/ 3 | 4 | 5 | 6 | 7 | Impress Tutorial </ title> 8 | <Meta http-equiv = "Content-Type" content = "text / html; charset = UTF-8"> 9 | </ Head> 10 | <Body> 11 | 12 | </ Body> 13 | </ Html> 14 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | .no-support-message { display:none; } 2 | .impress-not-supported .no-support-message { display:block; } 3 | 4 | /* additional styles just to make things look a bit nicer */ 5 | body { background:#EBEBEB; font:16px/24px "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; color:#333; } 6 | .step { width:940px; margin:0 auto 24px auto; text-align:center; } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | <!doctype html> 2 | <html> 3 | <head> 4 | <title>Impress Tutorial 5 | 6 | 7 | 8 | 9 |
10 |
11 | Your browser doesn't support impress.js. Try Chrome or Safari. 12 |
13 | 14 |
15 | This is my first slide. I start at 0,0. Welcome. 16 |
17 | 18 |
19 | This is slide 2. It slides left 500 pixels. 20 |
21 | 22 |
23 | This is slide 3. It slides down 400 pixels. 24 |
25 | 26 |
27 | This is slide 4. It scales everything up by a factor of 2. 28 |
29 | 30 |
31 | This is slide 5 and it rotates in. 32 |
33 | 34 |
35 | This is slide 6 and it has a 3D transition. 36 |
37 | 38 |
39 | This is slide 7 and it has a 3D transition AND a scale. 40 |
41 | 42 |
43 | 44 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /impress.js: -------------------------------------------------------------------------------- 1 | /** 2 | * impress.js 3 | * 4 | * impress.js is a presentation tool based on the power of CSS3 transforms and transitions 5 | * in modern browsers and inspired by the idea behind prezi.com. 6 | * 7 | * MIT Licensed. 8 | * 9 | * Copyright 2011 Bartek Szopka (@bartaz) 10 | */ 11 | 12 | (function ( document, window ) { 13 | 14 | // HELPER FUNCTIONS 15 | 16 | var pfx = (function () { 17 | 18 | var style = document.createElement('dummy').style, 19 | prefixes = 'Webkit Moz O ms Khtml'.split(' '), 20 | memory = {}; 21 | 22 | return function ( prop ) { 23 | if ( typeof memory[ prop ] === "undefined" ) { 24 | 25 | var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1), 26 | props = (prop + ' ' + prefixes.join(ucProp + ' ') + ucProp).split(' '); 27 | 28 | memory[ prop ] = null; 29 | for ( var i in props ) { 30 | if ( style[ props[i] ] !== undefined ) { 31 | memory[ prop ] = props[i]; 32 | break; 33 | } 34 | } 35 | 36 | } 37 | 38 | return memory[ prop ]; 39 | } 40 | 41 | })(); 42 | 43 | var arrayify = function ( a ) { 44 | return [].slice.call( a ); 45 | }; 46 | 47 | var css = function ( el, props ) { 48 | var key, pkey; 49 | for ( key in props ) { 50 | if ( props.hasOwnProperty(key) ) { 51 | pkey = pfx(key); 52 | if ( pkey != null ) { 53 | el.style[pkey] = props[key]; 54 | } 55 | } 56 | } 57 | return el; 58 | } 59 | 60 | var byId = function ( id ) { 61 | return document.getElementById(id); 62 | } 63 | 64 | var $ = function ( selector, context ) { 65 | context = context || document; 66 | return context.querySelector(selector); 67 | }; 68 | 69 | var $$ = function ( selector, context ) { 70 | context = context || document; 71 | return arrayify( context.querySelectorAll(selector) ); 72 | }; 73 | 74 | var translate = function ( t ) { 75 | return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) "; 76 | }; 77 | 78 | var rotate = function ( r, revert ) { 79 | var rX = " rotateX(" + r.x + "deg) ", 80 | rY = " rotateY(" + r.y + "deg) ", 81 | rZ = " rotateZ(" + r.z + "deg) "; 82 | 83 | return revert ? rZ+rY+rX : rX+rY+rZ; 84 | }; 85 | 86 | var scale = function ( s ) { 87 | return " scaleX(" + s.x + ") scaleY(" + s.y + ") scaleZ(" + s.z + ") "; 88 | } 89 | 90 | // CHECK SUPPORT 91 | 92 | var ua = navigator.userAgent.toLowerCase(); 93 | var impressSupported = ( pfx("perspective") != null ) && 94 | ( ua.search(/(iphone)|(ipod)|(ipad)|(android)/) == -1 ); 95 | 96 | // DOM ELEMENTS 97 | 98 | var impress = byId("impress"); 99 | 100 | if (!impressSupported) { 101 | impress.className = "impress-not-supported"; 102 | return; 103 | } else { 104 | impress.className = ""; 105 | } 106 | 107 | var canvas = document.createElement("div"); 108 | canvas.className = "canvas"; 109 | 110 | arrayify( impress.childNodes ).forEach(function ( el ) { 111 | canvas.appendChild( el ); 112 | }); 113 | impress.appendChild(canvas); 114 | 115 | var steps = $$(".step", impress); 116 | 117 | // SETUP 118 | // set initial values and defaults 119 | 120 | document.documentElement.style.height = "100%"; 121 | 122 | css(document.body, { 123 | height: "100%", 124 | overflow: "hidden" 125 | }); 126 | 127 | var props = { 128 | position: "absolute", 129 | transformOrigin: "top left", 130 | transition: "all 1s ease-in-out", 131 | transformStyle: "preserve-3d" 132 | } 133 | 134 | css(impress, props); 135 | css(impress, { 136 | top: "50%", 137 | left: "50%", 138 | perspective: "1000px" 139 | }); 140 | css(canvas, props); 141 | 142 | var current = { 143 | translate: { x: 0, y: 0, z: 0 }, 144 | rotate: { x: 0, y: 0, z: 0 }, 145 | scale: { x: 1, y: 1, z: 1 } 146 | }; 147 | 148 | steps.forEach(function ( el, idx ) { 149 | var data = el.dataset, 150 | step = { 151 | translate: { 152 | x: data.x || 0, 153 | y: data.y || 0, 154 | z: data.z || 0 155 | }, 156 | rotate: { 157 | x: data.rotateX || 0, 158 | y: data.rotateY || 0, 159 | z: data.rotateZ || data.rotate || 0 160 | }, 161 | scale: { 162 | x: data.scaleX || data.scale || 1, 163 | y: data.scaleY || data.scale || 1, 164 | z: data.scaleZ || 1 165 | } 166 | }; 167 | 168 | el.stepData = step; 169 | 170 | if ( !el.id ) { 171 | el.id = "step-" + (idx + 1); 172 | } 173 | 174 | css(el, { 175 | position: "absolute", 176 | transform: "translate(-50%,-50%)" + 177 | translate(step.translate) + 178 | rotate(step.rotate) + 179 | scale(step.scale), 180 | transformStyle: "preserve-3d" 181 | }); 182 | 183 | }); 184 | 185 | // making given step active 186 | 187 | var active = null; 188 | 189 | var select = function ( el ) { 190 | if ( !el || !el.stepData ) { 191 | // selected element is not defined as step 192 | return false; 193 | } 194 | 195 | // Sometimes it's possible to trigger focus on first link with some keyboard action. 196 | // Browser in such a case tries to scroll the page to make this element visible 197 | // (even that body overflow is set to hidden) and it breaks our careful positioning. 198 | // 199 | // So, as a lousy (and lazy) workaround we will make the page scroll back to the top 200 | // whenever slide is selected 201 | // 202 | // If you are reading this and know any better way to handle it, I'll be glad to hear about it! 203 | window.scrollTo(0, 0); 204 | 205 | var step = el.stepData; 206 | 207 | if ( active ) { 208 | active.classList.remove("active"); 209 | } 210 | el.classList.add("active"); 211 | 212 | impress.className = "step-" + el.id; 213 | 214 | // `#/step-id` is used instead of `#step-id` to prevent default browser 215 | // scrolling to element in hash 216 | window.location.hash = "#/" + el.id; 217 | 218 | var target = { 219 | rotate: { 220 | x: -parseInt(step.rotate.x, 10), 221 | y: -parseInt(step.rotate.y, 10), 222 | z: -parseInt(step.rotate.z, 10) 223 | }, 224 | scale: { 225 | x: 1 / parseFloat(step.scale.x), 226 | y: 1 / parseFloat(step.scale.y), 227 | z: 1 / parseFloat(step.scale.z) 228 | }, 229 | translate: { 230 | x: -step.translate.x, 231 | y: -step.translate.y, 232 | z: -step.translate.z 233 | } 234 | }; 235 | 236 | var zoomin = target.scale.x >= current.scale.x; 237 | 238 | css(impress, { 239 | // to keep the perspective look similar for different scales 240 | // we need to 'scale' the perspective, too 241 | perspective: step.scale.x * 1000 + "px", 242 | transform: scale(target.scale), 243 | transitionDelay: (zoomin ? "500ms" : "0ms") 244 | }); 245 | 246 | css(canvas, { 247 | transform: rotate(target.rotate, true) + translate(target.translate), 248 | transitionDelay: (zoomin ? "0ms" : "500ms") 249 | }); 250 | 251 | current = target; 252 | active = el; 253 | 254 | return el; 255 | } 256 | 257 | // EVENTS 258 | 259 | document.addEventListener("keydown", function ( event ) { 260 | if ( event.keyCode == 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) { 261 | var next = active; 262 | switch( event.keyCode ) { 263 | case 33: ; // pg up 264 | case 37: ; // left 265 | case 38: // up 266 | next = steps.indexOf( active ) - 1; 267 | next = next >= 0 ? steps[ next ] : steps[ steps.length-1 ]; 268 | break; 269 | case 9: ; // tab 270 | case 32: ; // space 271 | case 34: ; // pg down 272 | case 39: ; // right 273 | case 40: // down 274 | next = steps.indexOf( active ) + 1; 275 | next = next < steps.length ? steps[ next ] : steps[ 0 ]; 276 | break; 277 | } 278 | 279 | select(next); 280 | 281 | event.preventDefault(); 282 | } 283 | }, false); 284 | 285 | document.addEventListener("click", function ( event ) { 286 | // event delegation with "bubbling" 287 | // check if event target (or any of its parents is a link or a step) 288 | var target = event.target; 289 | while ( (target.tagName != "A") && 290 | (!target.stepData) && 291 | (target != document.body) ) { 292 | target = target.parentNode; 293 | } 294 | 295 | if ( target.tagName == "A" ) { 296 | var href = target.getAttribute("href"); 297 | 298 | // if it's a link to presentation step, target this step 299 | if ( href && href[0] == '#' ) { 300 | target = byId( href.slice(1) ); 301 | } 302 | } 303 | 304 | if ( select(target) ) { 305 | event.preventDefault(); 306 | } 307 | }); 308 | 309 | var getElementFromUrl = function () { 310 | // get id from url # by removing `#` or `#/` from the beginning, 311 | // so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work 312 | return byId( window.location.hash.replace(/^#\/?/,"") ); 313 | } 314 | 315 | window.addEventListener("hashchange", function () { 316 | select( getElementFromUrl() ); 317 | }, false); 318 | 319 | // START 320 | // by selecting step defined in url or first step of the presentation 321 | select(getElementFromUrl() || steps[0]); 322 | 323 | })(document, window); 324 | --------------------------------------------------------------------------------