Permalink
Browse files

fractional zoom and local tile cutter (php)

  • Loading branch information...
1 parent 4240299 commit bcd6d7b45ded044d834fb277d3e7f9db1873ed9c @dfacts committed Aug 10, 2010
Showing with 323 additions and 30 deletions.
  1. +49 −0 examples/fractional-zoom.html
  2. +7 −0 examples/marker-feature-info.html
  3. +5 −3 examples/marker-path-gpx.html
  4. +5 −3 examples/marker-path.html
  5. +46 −0 examples/tiles-local.html
  6. +62 −24 js/map.js
  7. +149 −0 tile.php
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html manifest="map.manifest">
+ <head>
+ <meta charset="utf-8">
+ <title>Slippy Map on Canvas (HTML5) | fractional zoom</title>
+ <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <link rel="apple-touch-icon-precomposed" href="../images/touch-icon.png" />
+ <link href="../css/map.css" rel="stylesheet" type="text/css" media="all" />
+ <link href="../css/ui.css" rel="stylesheet" type="text/css" media="all" />
+ <script src="../js/map.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ app.preInitListeners.push(function(){
+ app.markers =
+ { 'Berlin' :
+ { src : "../images/marker.png",
+ lon : 13.409500,
+ lat : 52.522488,
+ offsetX : -11,
+ offsetY : -25
+ },
+ 'Moskva' :
+ { src : "../images/marker.png",
+ lon : 37.617633,
+ lat : 55.755786,
+ offsetX : -11,
+ offsetY : -25
+ },
+ 'Hong Kong' :
+ { src : "../images/marker.png",
+ lon : 114.10494,
+ lat : 22.381111,
+ offsetX : -11,
+ offsetY : -25
+ }
+ }
+ });
+ </script>
+ </head>
+ <body>
+ <canvas id="map">
+ Your browser doesn't support canvas elements.
+ </canvas>
+ <ul id="buttons">
+ <li><a class="zoomin" href="javascript:;" onclick="app.zoomIn(0.2, false); return false;">+</a></li>
+ <li><a class="zoomout" href="javascript:;" onclick="app.zoomOut(0.2, false); return false;">-</a></li>
+ </ul>
+ </body>
+</html>
@@ -3,6 +3,13 @@
<head>
<meta charset="utf-8">
<title>Slippy Map on Canvas (HTML5) | simple path example</title>
+ <!--
+
+
+ does not work with fractional zoom - yet
+
+
+ -->
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="apple-touch-icon-precomposed" href="../images/touch-icon.png" />
@@ -45,14 +45,16 @@
}
}
app.preInitListeners.push(function(){
- drawPath = function(z,zp,sz,xMin,xMax,yMin,yMax){
+ drawPath = function(z, zp, sz, xMin, xMax, yMin, yMax, tilesize, diff){
+ var offsetX = Math.round((diff-1)*(xMax-xMin)/zp/2);
+ var offsetY = Math.round((diff-1)*(yMax-yMin)/zp/2);
function lon2x(lon){
- return Math.round((app.pos.lon2pos(lon)-xMin) / zp);
+ return Math.round((app.pos.lon2pos(lon)-xMin) / zp*diff)-offsetX;
}
function lat2y(lat){
- return Math.round((app.pos.lat2pos(lat)-yMin) / zp) ;
+ return Math.round((app.pos.lat2pos(lat)-yMin) / zp*diff)-offsetY;
}
for(t in tracks){
var track = tracks[t];
@@ -40,14 +40,16 @@
offsetY : -25
}
}
- drawPath = function(z,zp,sz,xMin,xMax,yMin,yMax){
+ drawPath = function(z,zp,sz,xMin,xMax,yMin,yMax, tilesize, diff){
+ var offsetX = Math.round((diff-1)*(xMax-xMin)/zp/2);
+ var offsetY = Math.round((diff-1)*(yMax-yMin)/zp/2);
function lon2x(lon){
- return Math.round((app.pos.lon2pos(lon)-xMin) / zp);
+ return Math.round((app.pos.lon2pos(lon)-xMin) / zp*diff)-offsetX;
}
function lat2y(lat){
- return Math.round((app.pos.lat2pos(lat)-yMin) / zp) ;
+ return Math.round((app.pos.lat2pos(lat)-yMin) / zp*diff)-offsetY;
}
for(t in tracks){
var track = tracks[t];
View
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html manifest="map.manifest">
+ <head>
+ <meta charset="utf-8">
+ <title>Slippy Map on Canvas (HTML5) | tiles from local source</title>
+ <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <link rel="apple-touch-icon-precomposed" href="../images/touch-icon.png" />
+ <link href="../css/map.css" rel="stylesheet" type="text/css" media="all" />
+ <link href="../css/ui.css" rel="stylesheet" type="text/css" media="all" />
+ <script type="text/javascript">
+ var now = function(){
+ return (new Date()).getTime();
+ }
+ var srcImagePath = "marker.png";
+ document.addEventListener('DOMContentLoaded', function(){
+ app = window.app || {};
+ app.tiles = app.tiles || {};
+ app.tiles.local = {
+ init : function(){
+ console.log("switching");
+ app.tileprovider = app.tiles.local.tileprovider;
+ },
+ recenter : function(){
+ app.recenter(0,0,0);
+ },
+ tileprovider : function(x,y,z){
+ return "../tile.php?src="+srcImagePath+"&x="+x+"&y="+y+"&z="+z+"&format=png&timestamp="+now();
+ }
+ };
+ app.preInitListeners.push(app.tiles.local.init);
+ app.postInitListeners.push(app.tiles.local.recenter);
+ }, null);
+ </script>
+ <script src="../js/map.js" type="text/javascript"></script>
+ </head>
+ <body>
+ <canvas id="map">
+ Your browser doesn't support canvas elements.
+ </canvas>
+ <ul id="buttons">
+ <li><a class="zoomin" href="javascript:;" onclick="app.zoomIn(); return false;">+</a></li>
+ <li><a class="zoomout" href="javascript:;" onclick="app.zoomOut(); return false;">-</a></li>
+ </ul>
+ </body>
+</html>
View
@@ -40,24 +40,38 @@
var url = "http://" + sub[rand(3)] + ".tile.openstreetmap.org/" + z + "/" + x + "/" + y + ".png";
return url;
},
- zoomIn: function () {
+ useFractionalZoom : true,
+ zoomIn: function (step, round) {
+ console.log(round);
if ($.app.pos.z < $.app.renderer.maxZ) {
- ++$.app.pos.z;
+ $.app.pos.z += step || 1;
+ if(round !== false) {
+ $.app.pos.z = $.Math.round($.app.pos.z);
+ }
+ if($.app.pos.z > $.app.renderer.maxZ) {
+ $.app.pos.z = $.app.renderer.maxZ;
+ }
$.app.renderer.refresh();
$.app.zoomed();
}
},
- zoomOut: function () {
+ zoomOut: function (step, round) {
if ($.app.pos.z > 0) {
- --$.app.pos.z;
+ $.app.pos.z -= step || 1;
+ if(round !== false) {
+ $.app.pos.z = $.Math.round($.app.pos.z);
+ }
+ if($.app.pos.z<0) {
+ $.app.pos.z = 0;
+ }
$.app.renderer.refresh();
$.app.zoomed();
}
},
recenter: function(lon,lat,zoom){
$.app.pos.x = $.app.pos.lon2pos(lon);
$.app.pos.y = $.app.pos.lat2pos(lat);
- if(zoom>0) $.app.pos.z = zoom;
+ if(zoom>=0) $.app.pos.z = zoom;
$.app.renderer.refresh();
},
/* keep track of zoom + pans */
@@ -137,11 +151,11 @@
delta = -event.detail / 3;
}
if (delta > 0) {
- $.app.zoomIn();
+ $.app.zoomIn(delta/100, false);
$.app.zoomed();
} else if (delta < 0) {
- $.app.zoomOut();
+ $.app.zoomOut(-delta/100, false);
$.app.zoomed();
}
},
@@ -157,7 +171,7 @@
$.app.pos.y += dY * $.Math.pow(2, $.app.renderer.maxZ - $.app.pos.z);
$.app.events.lastMouseX = x;
$.app.events.lastMouseY = y;
- $.app.zoomIn();
+ $.app.zoomIn(1, true);
},
/* maps touch events to mouse events */
touchHandler: function (event) {
@@ -205,11 +219,11 @@
var touches = event.changedTouches;
if (event.scale) {
if (event.scale > 1.5) {
- $.app.zoomIn();
+ $.app.zoomIn(0.1, false);
return true;
}
if (event.scale < 0.5) {
- $.app.zoomOut();
+ $.app.zoomOut(0.1, false);
return true;
}
}
@@ -251,7 +265,12 @@
id: 'tiles',
zindex: 0,
callback :
- function(z,zp,sz,xMin,xMax,yMin,yMax){
+ function(z,zp,sz,xMin,xMax,yMin,yMax, tilesize, zf){
+ $.app.renderer.context.fillStyle = "#dddddd";
+
+ var offsetX = $.Math.floor((zf-1)*(xMax-xMin)/zp/2);
+ var offsetY = $.Math.floor((zf-1)*(yMax-yMin)/zp/2);
+ var maxTileNumber = $.Math.pow(2,z)-1;
var encodeIndex = function (x, y, z) {
return x + "," + y + "," + z;
};
@@ -260,28 +279,41 @@
};
for (var x = $.Math.floor(xMin / sz); x < $.Math.ceil(xMax / sz); ++x) {
for (var y = $.Math.floor(yMin / sz); y < $.Math.ceil(yMax / sz); ++y) {
- var xoff = $.Math.round((x * sz - xMin) / zp);
- var yoff = $.Math.round((y * sz - yMin) / zp);
+ var xoff = $.Math.round((x * sz - xMin) / zp * zf)-offsetX;
+ var yoff = $.Math.round((y * sz - yMin) / zp * zf)-offsetY;
+
var tileKey = encodeIndex(x, y, z);
+ var tileKeyAbove = encodeIndex($.Math.floor(x/2), $.Math.floor(y/2), z-1);
+ if(x>maxTileNumber || y>maxTileNumber || x<0 || y<0){
+ $.app.renderer.context.fillStyle = "#dddddd";
+ $.app.renderer.context.fillRect(xoff, yoff, tilesize, tilesize);
+
+ } else {
if ($.app.renderer.tiles[tileKey] && $.app.renderer.tiles[tileKey].complete) {
try {
- $.app.renderer.context.drawImage($.app.renderer.tiles[tileKey], xoff, yoff);
+ $.app.renderer.context.drawImage($.app.renderer.tiles[tileKey], xoff, yoff, tilesize, tilesize);
} catch (e) {
$.app.renderer.context.fillStyle = "#dddddd";
- $.app.renderer.context.fillRect(xoff, yoff, $.app.renderer.tilesize, $.app.renderer.tilesize);
+ $.app.renderer.context.fillRect(xoff, yoff, tilesize, tilesize);
}
$.app.renderer.tiles[tileKey].lastDrawn = now();
- }
- else {
+ } else {
+ if ($.app.renderer.tiles[tileKeyAbove] && $.app.renderer.tiles[tileKeyAbove].complete){
+ var tileOffsetX = xoff-$.Math.floor((x-$.Math.ceil(x/2)*2)*tilesize*2);
+ var tileOffsetY = yoff-$.Math.floor((y-$.Math.ceil(y/2)*2)*tilesize*2);
+ $.app.renderer.context.drawImage($.app.renderer.tiles[tileKeyAbove], tileOffsetX, tileOffsetY,$.Math.ceil(2*tilesize), $.Math.ceil(2*tilesize));
+ } else {
+ $.app.renderer.context.fillStyle = "#dddddd";
+ $.app.renderer.context.fillRect(xoff, yoff, tilesize, tilesize);
+ }
if (!$.app.renderer.tiles[tileKey]) {
$.app.renderer.tiles[tileKey] = new Image();
- $.app.renderer.tiles[tileKey].src = $.app.tileprovider(x, y, $.app.pos.z, $.app.renderer.tiles[tileKey]);
+ $.app.renderer.tiles[tileKey].src = $.app.tileprovider(x, y, z, $.app.renderer.tiles[tileKey]);
$.app.renderer.tiles[tileKey].onload = function(){
$.app.renderer.refresh();
}
}
- $.app.renderer.context.fillStyle = "#dddddd";
- $.app.renderer.context.fillRect(xoff, yoff, $.app.renderer.tilesize, $.app.renderer.tilesize);
+ }
}
}
}
@@ -291,11 +323,13 @@
id: 'marker',
zindex: 99,
callback :
- function(z,zp,sz,xMin,xMax,yMin,yMax){
+ function(z,zp,sz,xMin,xMax,yMin,yMax, tilesize, zf){
+ var offsetX = $.Math.round((zf-1)*(xMax-xMin)/zp/2);
+ var offsetY = $.Math.round((zf-1)*(yMax-yMin)/zp/2);
for(var marker in $.app.markers){
if($.app.markers[marker].img && $.app.markers[marker].img.complete){
- x = $.Math.round(($.app.pos.lon2pos($.app.markers[marker].lon)-xMin) / zp) + $.app.markers[marker].offsetX;
- y = $.Math.round(($.app.pos.lat2pos($.app.markers[marker].lat)-yMin) / zp) + $.app.markers[marker].offsetY;
+ x = $.Math.round(($.app.pos.lon2pos($.app.markers[marker].lon)-xMin) / zp * zf) + $.app.markers[marker].offsetX - offsetX;
+ y = $.Math.round(($.app.pos.lat2pos($.app.markers[marker].lat)-yMin) / zp * zf) + $.app.markers[marker].offsetY - offsetY;
if(x>-50 && x<$.app.renderer.canvas.width+50 && y>-50 && y<$.app.renderer.canvas.height+50){
try {
$.app.renderer.context.drawImage($.app.markers[marker].img, x, y);
@@ -329,16 +363,19 @@
return (new $.Date()).getTime();
};
var z = $.app.pos.z;
+ var zf = $.app.useFractionalZoom?(1+z-parseInt(z)):1;
+ z = parseInt(z);
var zp = $.Math.pow(2, $.app.renderer.maxZ - z);
var w = $.app.renderer.canvas.width * zp;
var h = $.app.renderer.canvas.height * zp;
var sz = $.app.renderer.tilesize * zp;
+ var tilesize = $.Math.ceil($.app.renderer.tilesize*zf);
var xMin = $.app.pos.x - w / 2;
var yMin = $.app.pos.y - h / 2;
var xMax = $.app.pos.x + w / 2;
var yMax = $.app.pos.y + h / 2;
for (l in $.app.renderer.layers) {
- $.app.renderer.layers[l].callback(z,zp,sz,xMin,xMax,yMin,yMax);
+ $.app.renderer.layers[l].callback(z,zp,sz,xMin,xMax,yMin,yMax,tilesize, zf);
}
for (var i = 0; i < $.app.renderer.refreshListeners.length; i++) {
$.app.renderer.refreshListeners[i]();
@@ -349,6 +386,7 @@
refreshListeners : {},
/* garbage collector */
garbage: function () {
+ return;
if ($.app.renderer.tiles) {
var remove = [];
for (var key in $.app.renderer.tiles) {
Oops, something went wrong.

0 comments on commit bcd6d7b

Please sign in to comment.