Skip to content

Commit 077e4e7

Browse files
committed
fallback on zoom if css transforms are not supported
1 parent 8b950d0 commit 077e4e7

3 files changed

Lines changed: 168 additions & 31 deletions

File tree

css/main.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* These styles are only here to make the demo page prettier,
3+
* not used by zoom.js itself.
4+
*/
5+
16
html, body {
27
font-family: 'Lato', Times, 'Times New Roman', serif;
38
font-size: 16px;
@@ -20,6 +25,10 @@ header {
2025
line-height: 1.3em;
2126
}
2227

28+
header div {
29+
margin-top: 15px;
30+
}
31+
2332
h2 {
2433
margin-bottom: 5px;
2534

@@ -41,6 +50,10 @@ a {
4150
color: cyan;
4251
}
4352

53+
em {
54+
font-style: italic;
55+
}
56+
4457
#main {
4558
margin: 20px;
4659

index.html

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
<meta charset="utf-8">
66

77
<title>zoom.js</title>
8+
9+
<meta name="description" content="A minimal JavaScript API which enables zooming in on elements or rectangles in a document.">
10+
<meta name="author" content="Hakim El Hattab">
811

912
<link href='http://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
1013

@@ -15,8 +18,16 @@
1518
<body>
1619

1720
<header>
18-
<a href="https://github.com/hakimel/zoom.js">zoom.js</a> is a proof of concept JavaScript API for zooming in on DOM elements or points.<br>
19-
Click on any element on this page to zoom in and click again, or use <em>ESCAPE</em>, to zoom out.
21+
<a href="https://github.com/hakimel/zoom.js">zoom.js</a> is a <em>proof of concept</em> JavaScript API for zooming in on DOM elements or points.<br>
22+
Click on any element on this page to zoom in and click again, or use ESC, to zoom out.
23+
24+
<div>
25+
<a href="http://twitter.com/share" class="twitter-share-button" data-text="zoom.js - a JavaScript library that lets you zoom in on DOM elements. Created by @hakimel" data-url="http://lab.hakim.se/zoom-js" data-count="small" data-related="hakimel"></a>
26+
27+
<iframe id="facebook-button" src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fapp.hakim.se%2Fzoom-js%2F&layout=button_count&show_faces=false&width=93&action=like&font=arial&colorscheme=light&height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:85px; height:24px; position: relative; top: 4px;" allowTransparency="true"></iframe>
28+
29+
<script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
30+
</div>
2031
</header>
2132

2233
<div id="main">
@@ -75,5 +86,21 @@ <h2>I gotta piss</h2>
7586
} );
7687
</script>
7788

89+
90+
<!-- Everything below this point is unrelated to the library -->
91+
92+
<a href="https://github.com/hakimel/zoom.js"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://a248.e.akamai.net/assets.github.com/img/7afbc8b248c68eb468279e8c17986ad46549fb71/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub"></a>
93+
94+
<script>
95+
var _gaq = [['_setAccount', 'UA-15240703-1'], ['_trackPageview']];
96+
(function(d, t) {
97+
var g = d.createElement(t),
98+
s = d.getElementsByTagName(t)[0];
99+
g.async = true;
100+
g.src = ('https:' == location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
101+
s.parentNode.insertBefore(g, s);
102+
})(document, 'script');
103+
</script>
104+
78105
</body>
79106
</html>

js/zoom.js

Lines changed: 126 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,67 @@
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
*/
3255
var 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

Comments
 (0)