bookclub-advr

DSLC Advanced R Book Club
git clone https://git.eamoncaddigan.net/bookclub-advr.git
Log | Files | Refs | README | LICENSE

plugin.js (6779B)


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