1919 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2020 * THE SOFTWARE.
2121 *
22+ *
23+ * #############################################################################
24+ *
25+ *
2226 * zoom.js enables an easy API for magnifying the DOM on
23- * any given location. It also supports zooming in on a
24- * specific element, much like double tapping does in
25- * Mobile Safari.
27+ * any given location. It supports zooming in on either a
28+ * rectangle or element in the current document:
29+ *
30+ * zoom.in({
31+ * element: document.querySelector( 'img' )
32+ * });
33+ *
34+ * zoom.in({
35+ * x: 100,
36+ * y: 200,
37+ * width: 300,
38+ * height: 300
39+ * });
40+ *
41+ * zoom.out();
2642 *
27- * Currently just a proof of concept so expect bugs. Lots
28- * of bugs.
43+ *
44+ *
45+ * Note #1: this is currently just a proof of concept, don't
46+ * use it for anything important.
47+ *
48+ * Note #2: zoom.js works by adjusting the transform, transition,
49+ * transform-origin and zoom (IE) CSS properties of the <body> node
50+ * and may conflict with your own styles.
2951 *
3052 * @author Hakim El Hattab | http://hakim.se
53+ * @version 0.1
3154 */
3255var zoom = ( function ( ) {
3356
3457 // The current zoom level (scale)
35- var level = 1 ,
36- mouseX = 0 ,
37- mouseY = 0 ,
38- panEngageTimeout = - 1 ,
58+ var level = 1 ;
59+
60+ // The current mouse position, used for panning
61+ var mouseX = 0 ,
62+ mouseY = 0 ;
63+
64+ // Timeout before pan is activated
65+ var panEngageTimeout = - 1 ,
3966 panUpdateInterval = - 1 ;
4067
41- // The easing that will be applied when we zoom in/out
42- document . body . style . WebkitTransition = '-webkit-transform 0.8s ease' ;
43- document . body . style . MozTransition = '-moz-transform 0.8s ease' ;
44- document . body . style . msTransition = '-ms-transform 0.8s ease' ;
45- document . body . style . OTransition = '-o-transform 0.8s ease' ;
46- document . body . style . transition = 'transform 0.8s ease' ;
68+ // Check for transform support so that we can fallback otherwise
69+ var supportsTransforms = document . body . style . WebkitTransform !== undefined ||
70+ document . body . style . MozTransform !== undefined ||
71+ document . body . style . msTransform !== undefined ||
72+ document . body . style . OTransform !== undefined ||
73+ document . body . style . transform !== undefined ;
74+
75+ if ( supportsTransforms ) {
76+ // The easing that will be applied when we zoom in/out
77+ document . body . style . WebkitTransition = '-webkit-transform 0.8s ease' ;
78+ document . body . style . MozTransition = '-moz-transform 0.8s ease' ;
79+ document . body . style . msTransition = '-ms-transform 0.8s ease' ;
80+ document . body . style . OTransition = '-o-transform 0.8s ease' ;
81+ document . body . style . transition = 'transform 0.8s ease' ;
82+ }
4783
4884 // Zoom out if the user hits escape
4985 document . addEventListener ( 'keyup' , function ( event ) {
@@ -60,16 +96,63 @@ var zoom = (function(){
6096 }
6197 } ) ;
6298
63- function prefix ( property , value ) {
64- document . body . style [ 'Webkit' + property ] = value ;
65- document . body . style [ 'Moz' + property ] = value ;
66- document . body . style [ 'ms' + property ] = value ;
67- document . body . style [ 'O' + property ] = value ;
68- document . body . style [ property ] = value ;
99+ /**
100+ * Applies the CSS required to zoom in, prioritizes use of CSS3
101+ * transforms but falls back on zoom for IE.
102+ *
103+ * @param {Number } pageOffsetX
104+ * @param {Number } pageOffsetY
105+ * @param {Number } elementOffsetX
106+ * @param {Number } elementOffsetY
107+ * @param {Number } scale
108+ */
109+ function magnify ( pageOffsetX , pageOffsetY , elementOffsetX , elementOffsetY , scale ) {
110+ if ( supportsTransforms ) {
111+ var origin = pageOffsetX + 'px ' + pageOffsetY + 'px' ,
112+ transform = 'translate( ' + - elementOffsetX + 'px, ' + - elementOffsetY + 'px ) scale( ' + scale + ' )' ;
113+
114+ document . body . style . WebkitTransformOrigin = origin ;
115+ document . body . style . MozTransformOrigin = origin ;
116+ document . body . style . msTransformOrigin = origin ;
117+ document . body . style . OTransformOrigin = origin ;
118+ document . body . style . transformOrigin = origin ;
119+
120+ document . body . style . WebkitTransform = transform ;
121+ document . body . style . MozTransform = transform ;
122+ document . body . style . msTransform = transform ;
123+ document . body . style . OTransform = transform ;
124+ document . body . style . transform = transform ;
125+ }
126+ else {
127+ // Reset all values
128+ if ( scale === 1 ) {
129+ document . body . style . position = '' ;
130+ document . body . style . left = '' ;
131+ document . body . style . top = '' ;
132+ document . body . style . width = '' ;
133+ document . body . style . height = '' ;
134+ document . body . style . zoom = '' ;
135+ }
136+ // Apply scale
137+ else {
138+ document . body . style . position = 'relative' ;
139+ document . body . style . left = ( - ( pageOffsetX + elementOffsetX ) / scale ) + 'px' ;
140+ document . body . style . top = ( - ( pageOffsetY + elementOffsetY ) / scale ) + 'px' ;
141+ document . body . style . width = ( scale * 100 ) + '%' ;
142+ document . body . style . height = ( scale * 100 ) + '%' ;
143+ document . body . style . zoom = scale ;
144+ }
145+ }
146+
147+ level = scale ;
69148 }
70149
150+ /**
151+ * Pan the document when the mosue cursor approaches the edges
152+ * of the window.
153+ */
71154 function pan ( ) {
72- var range = 0.15 ,
155+ var range = 0.12 ,
73156 rangeX = window . innerWidth * range ,
74157 rangeY = window . innerHeight * range ;
75158
@@ -93,7 +176,19 @@ var zoom = (function(){
93176 }
94177
95178 return {
179+ /**
180+ * Zooms in on either a rectangle or HTML element.
181+ *
182+ * @param {Object } options
183+ * - element: HTML element to zoom in on
184+ * OR
185+ * - x/y: coordinates in non-transformed space to zoom in on
186+ * - width/height: the portion of the screen to zoom in on
187+ * - scale: can be used instead of width/height explicitly set scale
188+ */
96189 in : function ( options ) {
190+ // Due to an implementation limitation we can't zoom in
191+ // to another element without zooming our first
97192 if ( level !== 1 ) {
98193 zoom . out ( ) ;
99194 }
@@ -103,6 +198,7 @@ var zoom = (function(){
103198
104199 // If an element is set, that takes precedence
105200 if ( ! ! options . element ) {
201+ // Space around the zoomed in element to leave on screen
106202 var padding = 20 ;
107203
108204 options . width = options . element . getBoundingClientRect ( ) . width + ( padding * 2 ) ;
@@ -120,28 +216,29 @@ var zoom = (function(){
120216 options . x *= options . scale ;
121217 options . y *= options . scale ;
122218
123- prefix ( 'TransformOrigin' , window . scrollX + 'px ' + window . scrollY + 'px' ) ;
124- prefix ( 'Transform' , 'translate(' + - options . x + 'px, ' + - options . y + 'px) scale(' + options . scale + ')' ) ;
125-
126- level = options . scale ;
219+ magnify ( window . scrollX , window . scrollY , options . x , options . y , options . scale ) ;
127220
221+ // Wait with engaging panning as it may conflict with the
222+ // zoom transition
128223 panEngageTimeout = setTimeout ( function ( ) {
129224 panUpdateInterval = setInterval ( pan , 1000 / 60 ) ;
130225 } , 800 ) ;
131226 }
132227 }
133228 } ,
134229
230+ /**
231+ * Resets the document zoom state to its default.
232+ */
135233 out : function ( ) {
136234 clearTimeout ( panEngageTimeout ) ;
137235 clearInterval ( panUpdateInterval ) ;
138236
139- prefix ( 'TransformOrigin' , window . scrollX + 'px ' + window . scrollY + 'px' ) ;
140- prefix ( 'Transform' , '' ) ;
237+ magnify ( window . scrollX , window . scrollY , 0 , 0 , 1 ) ;
141238
142239 level = 1 ;
143240 } ,
144-
241+
145242 zoomLevel : function ( ) {
146243 return level ;
147244 }
0 commit comments