presentations

Presentations
Log | Files | Refs

zoom.js (7821B)


      1 // Custom reveal.js integration
      2 var RevealZoom = (function(){
      3 
      4 	return {
      5 		init: function() {
      6 
      7 			Reveal.getRevealElement().addEventListener( 'mousedown', function( event ) {
      8 				var defaultModifier = /Linux/.test( window.navigator.platform ) ? 'ctrl' : 'alt';
      9 
     10 				var modifier = ( Reveal.getConfig().zoomKey ? Reveal.getConfig().zoomKey : defaultModifier ) + 'Key';
     11 				var zoomLevel = ( Reveal.getConfig().zoomLevel ? Reveal.getConfig().zoomLevel : 2 );
     12 
     13 				if( event[ modifier ] && !Reveal.isOverview() ) {
     14 					event.preventDefault();
     15 
     16 					zoom.to({
     17 						x: event.clientX,
     18 						y: event.clientY,
     19 						scale: zoomLevel,
     20 						pan: false
     21 					});
     22 				}
     23 			} );
     24 
     25 		}
     26 	}
     27 
     28 })();
     29 
     30 Reveal.registerPlugin( 'zoom', RevealZoom );
     31 
     32 /*!
     33  * zoom.js 0.3 (modified for use with reveal.js)
     34  * http://lab.hakim.se/zoom-js
     35  * MIT licensed
     36  *
     37  * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
     38  */
     39 var zoom = (function(){
     40 
     41 	// The current zoom level (scale)
     42 	var level = 1;
     43 
     44 	// The current mouse position, used for panning
     45 	var mouseX = 0,
     46 		mouseY = 0;
     47 
     48 	// Timeout before pan is activated
     49 	var panEngageTimeout = -1,
     50 		panUpdateInterval = -1;
     51 
     52 	// Check for transform support so that we can fallback otherwise
     53 	var supportsTransforms = 	'WebkitTransform' in document.body.style ||
     54 								'MozTransform' in document.body.style ||
     55 								'msTransform' in document.body.style ||
     56 								'OTransform' in document.body.style ||
     57 								'transform' in document.body.style;
     58 
     59 	if( supportsTransforms ) {
     60 		// The easing that will be applied when we zoom in/out
     61 		document.body.style.transition = 'transform 0.8s ease';
     62 		document.body.style.OTransition = '-o-transform 0.8s ease';
     63 		document.body.style.msTransition = '-ms-transform 0.8s ease';
     64 		document.body.style.MozTransition = '-moz-transform 0.8s ease';
     65 		document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
     66 	}
     67 
     68 	// Zoom out if the user hits escape
     69 	document.addEventListener( 'keyup', function( event ) {
     70 		if( level !== 1 && event.keyCode === 27 ) {
     71 			zoom.out();
     72 		}
     73 	} );
     74 
     75 	// Monitor mouse movement for panning
     76 	document.addEventListener( 'mousemove', function( event ) {
     77 		if( level !== 1 ) {
     78 			mouseX = event.clientX;
     79 			mouseY = event.clientY;
     80 		}
     81 	} );
     82 
     83 	/**
     84 	 * Applies the CSS required to zoom in, prefers the use of CSS3
     85 	 * transforms but falls back on zoom for IE.
     86 	 *
     87 	 * @param {Object} rect
     88 	 * @param {Number} scale
     89 	 */
     90 	function magnify( rect, scale ) {
     91 
     92 		var scrollOffset = getScrollOffset();
     93 
     94 		// Ensure a width/height is set
     95 		rect.width = rect.width || 1;
     96 		rect.height = rect.height || 1;
     97 
     98 		// Center the rect within the zoomed viewport
     99 		rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2;
    100 		rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2;
    101 
    102 		if( supportsTransforms ) {
    103 			// Reset
    104 			if( scale === 1 ) {
    105 				document.body.style.transform = '';
    106 				document.body.style.OTransform = '';
    107 				document.body.style.msTransform = '';
    108 				document.body.style.MozTransform = '';
    109 				document.body.style.WebkitTransform = '';
    110 			}
    111 			// Scale
    112 			else {
    113 				var origin = scrollOffset.x +'px '+ scrollOffset.y +'px',
    114 					transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')';
    115 
    116 				document.body.style.transformOrigin = origin;
    117 				document.body.style.OTransformOrigin = origin;
    118 				document.body.style.msTransformOrigin = origin;
    119 				document.body.style.MozTransformOrigin = origin;
    120 				document.body.style.WebkitTransformOrigin = origin;
    121 
    122 				document.body.style.transform = transform;
    123 				document.body.style.OTransform = transform;
    124 				document.body.style.msTransform = transform;
    125 				document.body.style.MozTransform = transform;
    126 				document.body.style.WebkitTransform = transform;
    127 			}
    128 		}
    129 		else {
    130 			// Reset
    131 			if( scale === 1 ) {
    132 				document.body.style.position = '';
    133 				document.body.style.left = '';
    134 				document.body.style.top = '';
    135 				document.body.style.width = '';
    136 				document.body.style.height = '';
    137 				document.body.style.zoom = '';
    138 			}
    139 			// Scale
    140 			else {
    141 				document.body.style.position = 'relative';
    142 				document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px';
    143 				document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px';
    144 				document.body.style.width = ( scale * 100 ) + '%';
    145 				document.body.style.height = ( scale * 100 ) + '%';
    146 				document.body.style.zoom = scale;
    147 			}
    148 		}
    149 
    150 		level = scale;
    151 
    152 		if( document.documentElement.classList ) {
    153 			if( level !== 1 ) {
    154 				document.documentElement.classList.add( 'zoomed' );
    155 			}
    156 			else {
    157 				document.documentElement.classList.remove( 'zoomed' );
    158 			}
    159 		}
    160 	}
    161 
    162 	/**
    163 	 * Pan the document when the mosue cursor approaches the edges
    164 	 * of the window.
    165 	 */
    166 	function pan() {
    167 		var range = 0.12,
    168 			rangeX = window.innerWidth * range,
    169 			rangeY = window.innerHeight * range,
    170 			scrollOffset = getScrollOffset();
    171 
    172 		// Up
    173 		if( mouseY < rangeY ) {
    174 			window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
    175 		}
    176 		// Down
    177 		else if( mouseY > window.innerHeight - rangeY ) {
    178 			window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
    179 		}
    180 
    181 		// Left
    182 		if( mouseX < rangeX ) {
    183 			window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
    184 		}
    185 		// Right
    186 		else if( mouseX > window.innerWidth - rangeX ) {
    187 			window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
    188 		}
    189 	}
    190 
    191 	function getScrollOffset() {
    192 		return {
    193 			x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
    194 			y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset
    195 		}
    196 	}
    197 
    198 	return {
    199 		/**
    200 		 * Zooms in on either a rectangle or HTML element.
    201 		 *
    202 		 * @param {Object} options
    203 		 *   - element: HTML element to zoom in on
    204 		 *   OR
    205 		 *   - x/y: coordinates in non-transformed space to zoom in on
    206 		 *   - width/height: the portion of the screen to zoom in on
    207 		 *   - scale: can be used instead of width/height to explicitly set scale
    208 		 */
    209 		to: function( options ) {
    210 
    211 			// Due to an implementation limitation we can't zoom in
    212 			// to another element without zooming out first
    213 			if( level !== 1 ) {
    214 				zoom.out();
    215 			}
    216 			else {
    217 				options.x = options.x || 0;
    218 				options.y = options.y || 0;
    219 
    220 				// If an element is set, that takes precedence
    221 				if( !!options.element ) {
    222 					// Space around the zoomed in element to leave on screen
    223 					var padding = 20;
    224 					var bounds = options.element.getBoundingClientRect();
    225 
    226 					options.x = bounds.left - padding;
    227 					options.y = bounds.top - padding;
    228 					options.width = bounds.width + ( padding * 2 );
    229 					options.height = bounds.height + ( padding * 2 );
    230 				}
    231 
    232 				// If width/height values are set, calculate scale from those values
    233 				if( options.width !== undefined && options.height !== undefined ) {
    234 					options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
    235 				}
    236 
    237 				if( options.scale > 1 ) {
    238 					options.x *= options.scale;
    239 					options.y *= options.scale;
    240 
    241 					magnify( options, options.scale );
    242 
    243 					if( options.pan !== false ) {
    244 
    245 						// Wait with engaging panning as it may conflict with the
    246 						// zoom transition
    247 						panEngageTimeout = setTimeout( function() {
    248 							panUpdateInterval = setInterval( pan, 1000 / 60 );
    249 						}, 800 );
    250 
    251 					}
    252 				}
    253 			}
    254 		},
    255 
    256 		/**
    257 		 * Resets the document zoom state to its default.
    258 		 */
    259 		out: function() {
    260 			clearTimeout( panEngageTimeout );
    261 			clearInterval( panUpdateInterval );
    262 
    263 			magnify( { x: 0, y: 0 }, 1 );
    264 
    265 			level = 1;
    266 		},
    267 
    268 		// Alias
    269 		magnify: function( options ) { this.to( options ) },
    270 		reset: function() { this.out() },
    271 
    272 		zoomLevel: function() {
    273 			return level;
    274 		}
    275 	}
    276 
    277 })();