Permalink
Browse files

added smooth zooming and panning implementation

  • Loading branch information...
1 parent 9c5df4d commit bc49fee1ba2d04f5c2cbdb10ef51813696ac647c @RandomEtc RandomEtc committed Sep 27, 2010
Showing with 160 additions and 0 deletions.
  1. +160 −0 examples/zoompan/index.html
  2. BIN examples/zoompan/zoompan.pdf
View
@@ -0,0 +1,160 @@
+<html>
+<head>
+<title>Modest Maps JS - Smooth Efficient Zooming and Panning</title>
+<script type="text/javascript" src="../../modestmaps.js"></script>
+<script type="text/javascript">
+
+var map;
+
+function initMap() {
+
+ var container = document.getElementById('container');
+
+ var template = 'http://{S}tile.openstreetmap.org/{Z}/{X}/{Y}.png';
+ var subdomains = [ 'a.', 'b.', 'c.', ''];
+ var provider = new com.modestmaps.TemplatedMapProvider(template, subdomains);
+
+ map = new com.modestmaps.Map('map', provider);
+
+ map.setCenterZoom(new com.modestmaps.Location(37.811530, -122.2666097), 14);
+
+ //animateCenterZoom(new com.modestmaps.Location(37.770, -122.424), 16);
+ animateCenterZoom(new com.modestmaps.Location(51.514, -0.113), 18);
+}
+
+function animateCenterZoom(l1, z1) {
+
+ var start = map.provider.locationCoordinate(map.getCenter()).zoomTo(0),
+ end = map.provider.locationCoordinate(l1).zoomTo(0);
+
+ var c0 = { x: start.column, y: start.row },
+ c1 = { x: end.column, y: end.row };
+
+ // how much world can we see at zoom 0?
+ var topLeft = map.pointCoordinate(new com.modestmaps.Point(0,0)).zoomTo(0);
+ var bottomRight = map.pointCoordinate(map.dimensions).zoomTo(0);
+ var w0 = Math.max(bottomRight.column-topLeft.column, bottomRight.row-topLeft.row);
+
+ // z1 is ds times bigger than this zoom:
+ var ds = Math.pow(2, z1 - map.getZoom());
+
+ // so how much world at zoom z1?
+ var w1 = w0 / ds;
+
+ // GO!
+ animateStep(c0, w0, c1, w1);
+
+}
+
+/*
+
+ From "Smooth and efficient zooming and panning"
+ by Jarke J. van Wijk and Wim A.A. Nuij
+
+ You only need to understand section 3 (equations 1 through 5)
+ and then you can skip to equation 9, implemented below:
+
+*/
+
+function sq(n) { return n*n; }
+function dist(a,b) { return Math.sqrt(sq(b.x-a.x)+sq(b.y-a.y)); }
+function lerp1(a,b,p) { return a + ((b-a) * p) }
+function lerp2(a,b,p) { return { x: lerp1(a.x,b.x,p), y: lerp1(a.y,b.y,p) }; }
+function cosh(x) { return (Math.pow(Math.E,x) + Math.pow(Math.E,-x)) / 2; }
+function sinh(x) { return (Math.pow(Math.E,x) - Math.pow(Math.E,-x)) / 2; }
+function tanh(x) { return sinh(x) / cosh(x); }
+
+function animateStep(c0,w0,c1,w1,V,rho) {
+
+ // see section 6 for user testing to derive these values (they can be tuned)
+ if (V === undefined) V = 0.9;
+ if (rho === undefined) rho = 1.42
+
+ // simple interpolation of positions will be fine:
+ var u0 = 0,
+ u1 = dist(c0,c1);
+
+ if (console && console.log) console.log('u0 = ' + u0);
+ if (console && console.log) console.log('u1 = ' + u1);
+
+ // i = 0 or 1
+ function b(i) {
+ var n = sq(w1) - sq(w0) + ((i ? -1 : 1) * Math.pow(rho,4) * sq(u1-u0));
+ var d = 2 * (i ? w1 : w0) * sq(rho) * (u1-u0);
+ return n / d;
+ }
+
+ // give this a b(0) or b(1)
+ function r(b) {
+ return Math.log(-b + Math.sqrt(sq(b)+1));
+ }
+
+ var r0 = r(b(0)),
+ r1 = r(b(1)),
+ S = (r1-r0) / rho; // "distance"
+
+ if (console && console.log) console.log('r0 = ' + r0);
+ if (console && console.log) console.log('r1 = ' + r1);
+ if (console && console.log) console.log('S = ' + S);
+
+ function u(s) {
+ var a = w0/sq(rho),
+ b = a * cosh(r0) * tanh(rho*s + r0),
+ c = a * sinh(r0);
+ return b - c + u0;
+ }
+
+ function w(s) {
+ return w0 * cosh(r0) / cosh(rho*s + r0);
+ }
+
+ if (console && console.log) console.log('max t = ' + (S / V));
+
+ var t0 = Date.now();
+ var interval = setInterval(function() {
+ var t1 = Date.now();
+ var t = (t1 - t0) / 1000.0;
+ var s = V * t;
+ if (s > S) {
+ s = S;
+ clearInterval(interval);
+ }
+ var us = u(s);
+ var pos = lerp2(c0,c1,(us-u0)/(u1-u0));
+ applyPos(pos, w(s));
+ }, 40);
+
+}
+
+function applyPos(pos,w) {
+ var c = new com.modestmaps.Coordinate(pos.y,pos.x,0);
+ var l = map.provider.coordinateLocation(c);
+
+ // how much world can we see at zoom 0?
+ var topLeft = map.pointCoordinate(new com.modestmaps.Point(0,0)).zoomTo(0);
+ var bottomRight = map.pointCoordinate(map.dimensions).zoomTo(0);
+ var w0 = Math.max(bottomRight.column-topLeft.column, bottomRight.row-topLeft.row);
+
+ // so what's our new zoom?
+ var z = map.getZoom() + (Math.log(w0/w) / Math.LN2)
+ map.setCenterZoom(l,z);
+}
+
+</script>
+<style type="text/css">
+body {
+ margin: 0;
+ padding: 0;
+ border: 0
+}
+#map {
+ width: 100%;
+ height: 100%;
+}
+</style>
+</head>
+<body onload="initMap()">
+ <div id="map">
+ </div>
+</body>
+</html>
Binary file not shown.

0 comments on commit bc49fee

Please sign in to comment.