diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc9b9bb..d668d750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,16 @@ Leaflet Changelog ## 0.2 (master) * Added **WMS support** (`TileLayer.WMS`), currently EPSG:3857 only. + * Added `TileLayer.Canvas` for easy creation of canvas-based tile layers. * `Circle` is now zoom-dependent (with radius in meters); circle of a permanent size is now called `L.CircleMarker`. * Added `mouseover` and `mouseout` events to map, markers and paths; added map `mousemove` event. * Added `setLatLngs`, `spliceLatLngs`, `addLatLng`, `getLatLngs` methods to polylines and polygons. * `LatLngBounds contains` method now accepts `LatLng` in addition to `LatLngBounds`, the same for `Bounds contains` and `Point` + * Added TMS tile numbering support through `TileLayer` `scheme: 'tms'` option (by [@tmcw](https://github.com/tmcw)). * Added `opacity` option for tile layers. * Added `setLatLng` method to `L.Marker`. * Added `maxZoom` argument to `map.locateAndSetView` method. + * Added `DomEvent.getTarget` method. * Improved geolocation error handling: better error messages, explicit timeout, set world view on locateAndSetView failure. [#61](http://github.com/CloudMade/Leaflet/issues/61) * Disabled zoom animation on Android by default because it's buggy on some devices (will be enabled back when it's stable enough). [#32](http://github.com/CloudMade/Leaflet/issues/32) * Fixed a bug where map would occasionally break while multi-touch-zooming on iOS. [#32](http://github.com/CloudMade/Leaflet/issues/32) diff --git a/build/Makefile b/build/Makefile new file mode 100644 index 00000000..cba4f1d4 --- /dev/null +++ b/build/Makefile @@ -0,0 +1,54 @@ +../dist/leaflet.js: Makefile + java -jar ../lib/closure-compiler/compiler.jar \ + --js ../src/Leaflet.js \ + --js ../src/core/Util.js \ + --js ../src/core/Class.js \ + --js ../src/core/Events.js \ + --js ../src/core/Browser.js \ + --js ../src/geometry/Point.js \ + --js ../src/geometry/Bounds.js \ + --js ../src/geometry/Transformation.js \ + --js ../src/geometry/LineUtil.js \ + --js ../src/geometry/PolyUtil.js \ + --js ../src/dom/DomEvent.js \ + --js ../src/dom/DomEvent.DoubleTap.js \ + --js ../src/dom/DomUtil.js \ + --js ../src/dom/Draggable.js \ + --js ../src/dom/transition/Transition.js \ + --js ../src/dom/transition/Transition.Native.js \ + --js ../src/dom/transition/Transition.Timer.js \ + --js ../src/geo/LatLng.js \ + --js ../src/geo/LatLngBounds.js \ + --js ../src/geo/Projection.js \ + --js ../src/layer/tile/TileLayer.js \ + --js ../src/layer/tile/TileLayer.WMS.js \ + --js ../src/layer/tile/TileLayer.Canvas.js \ + --js ../src/layer/ImageOverlay.js \ + --js ../src/layer/Popup.js \ + --js ../src/layer/marker/Icon.js \ + --js ../src/layer/marker/Marker.js \ + --js ../src/layer/marker/Marker.Popup.js \ + --js ../src/layer/vector/Path.js \ + --js ../src/layer/vector/Path.VML.js \ + --js ../src/layer/vector/Path.Popup.js \ + --js ../src/layer/vector/Polyline.js \ + --js ../src/layer/vector/Polygon.js \ + --js ../src/layer/vector/Circle.js \ + --js ../src/layer/vector/CircleMarker.js \ + --js ../src/handler/Handler.js \ + --js ../src/handler/MapDrag.js \ + --js ../src/handler/TouchZoom.js \ + --js ../src/handler/ScrollWheelZoom.js \ + --js ../src/handler/DoubleClickZoom.js \ + --js ../src/handler/ShiftDragZoom.js \ + --js ../src/handler/MarkerDrag.js \ + --js ../src/control/Control.js \ + --js ../src/control/Control.Zoom.js \ + --js ../src/control/Control.Attribution.js \ + --js ../src/map/Map.js \ + --js ../src/map/ext/Map.Geolocation.js \ + --js ../src/map/ext/Map.Popup.js \ + --js ../src/map/ext/Map.PanAnimation.js \ + --js ../src/map/ext/Map.ZoomAnimation.js \ + --js ../src/map/ext/Map.Control.js \ + --js_output_file ../dist/leaflet.js diff --git a/build/build.bat b/build/build.bat index 29232526..72302b83 100644 --- a/build/build.bat +++ b/build/build.bat @@ -20,8 +20,9 @@ java -jar ../lib/closure-compiler/compiler.jar ^ --js ../src/geo/LatLng.js ^ --js ../src/geo/LatLngBounds.js ^ --js ../src/geo/Projection.js ^ ---js ../src/layer/TileLayer.js ^ ---js ../src/layer/TileLayer.WMS.js ^ +--js ../src/layer/tile/TileLayer.js ^ +--js ../src/layer/tile/TileLayer.WMS.js ^ +--js ../src/layer/tile/TileLayer.Canvas.js ^ --js ../src/layer/ImageOverlay.js ^ --js ../src/layer/Popup.js ^ --js ../src/layer/marker/Icon.js ^ diff --git a/build/deps.js b/build/deps.js index 2e91222f..27ede35b 100644 --- a/build/deps.js +++ b/build/deps.js @@ -18,17 +18,23 @@ var deps = { TileLayer: { - src: ['layer/TileLayer.js'], + src: ['layer/tile/TileLayer.js'], desc: 'The base class for displaying tile layers on the map.', heading: 'Layers' }, TileLayerWMS: { - src: ['layer/TileLayer.WMS.js'], + src: ['layer/tile/TileLayer.WMS.js'], desc: 'WMS tile layer, currently only supports EPSG:3857.', deps: ['TileLayer'] }, + TileLayerCanvas: { + src: ['layer/tile/TileLayer.Canvas.js'], + desc: 'Tile layer made from canvases (for custom drawing purposes).', + deps: ['TileLayer'] + }, + ImageOverlay: { src: ['layer/ImageOverlay.js'], desc: 'Used to display an image over a particular rectangular area of the map.' diff --git a/debug/include.js b/debug/include.js index f231a1a3..275f0029 100644 --- a/debug/include.js +++ b/debug/include.js @@ -27,8 +27,9 @@ 'geo/LatLngBounds.js', 'geo/Projection.js', - 'layer/TileLayer.js', - 'layer/TileLayer.WMS.js', + 'layer/tile/TileLayer.js', + 'layer/tile/TileLayer.WMS.js', + 'layer/tile/TileLayer.Canvas.js', 'layer/ImageOverlay.js', 'layer/Popup.js', diff --git a/debug/map/canvas.html b/debug/map/canvas.html new file mode 100644 index 00000000..6f6fab8c --- /dev/null +++ b/debug/map/canvas.html @@ -0,0 +1,46 @@ + + + + Leaflet debug page + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/dist/leaflet.js b/dist/leaflet.js index 8bfd4c07..8e970d29 100644 --- a/dist/leaflet.js +++ b/dist/leaflet.js @@ -17,8 +17,8 @@ b,d.y);else if(c&4)return new L.Point(a.x+e*(f.y-a.y)/b,f.y);else if(c&2)return 0)return this._sqDist(a,b);if(f>1)return this._sqDist(a,c);b=new L.Point(b.x+d*f,b.y+e*f);return this._sqDist(a,b)}};L.PolyUtil={};L.PolyUtil.clipPolygon=function(a,b){var c,d=[1,4,2,8],e,f,g,h,i,j,k=L.LineUtil;e=0;for(i=a.length;e0&&c<=h;f=b}}function e(){if(g)i.type="dblclick",b(i),f=null}var f,g=!1,h=250,i;a["_leaflet_touchstart"+c]=d;a["_leaflet_touchend"+c]=e;a.addEventListener("touchstart",d,!1);a.addEventListener("touchend",e,!1)},removeDoubleTapListener:function(a,b){a.removeEventListener(a,a["_leaflet_touchstart"+b],!1);a.removeEventListener(a,a["_leaflet_touchend"+b], +"mousedown",L.DomEvent.stopPropagation);L.DomEvent.addListener(a,"click",L.DomEvent.stopPropagation);L.DomEvent.addListener(a,"dblclick",L.DomEvent.stopPropagation)},preventDefault:function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},getTarget:function(a){if((a=a.target||a.srcElement)&&a.nodeType==3)a=a.parentNode;return a},getMousePosition:function(a,b){var c=new L.Point(a.pageX?a.pageX:a.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,a.pageY?a.pageY:a.clientY+ +document.body.scrollTop+document.documentElement.scrollTop);return b?c.subtract(L.DomUtil.getCumulativeOffset(b)):c},getWheelDelta:function(a){var b=0;a.wheelDelta&&(b=a.wheelDelta/120);a.detail&&(b=-a.detail/3);return b}};L.Util.extend(L.DomEvent,{addDoubleTapListener:function(a,b,c){function d(a){if(a.touches.length==1){var b=Date.now(),c=b-(f||b);i=a.touches[0];g=c>0&&c<=h;f=b}}function e(){if(g)i.type="dblclick",b(i),f=null}var f,g=!1,h=250,i;a["_leaflet_touchstart"+c]=d;a["_leaflet_touchend"+c]=e;a.addEventListener("touchstart",d,!1);a.addEventListener("touchend",e,!1)},removeDoubleTapListener:function(a,b){a.removeEventListener(a,a["_leaflet_touchstart"+b],!1);a.removeEventListener(a,a["_leaflet_touchend"+b], !1)}});L.DomUtil={get:function(a){return typeof a=="string"?document.getElementById(a):a},getStyle:function(a,b){var c=a.style[b];typeof c=="undefined"&&a.currentStyle&&(c=a.currentStyle[b]);typeof c=="undefined"&&(c=(c=document.defaultView.getComputedStyle(a,null))?c[b]:null);return c=="auto"?null:c},getCumulativeOffset:function(a){var b=0,c=0;do b+=a.offsetTop||0,c+=a.offsetLeft||0,a=a.offsetParent;while(a);return new L.Point(c,b)},create:function(a,b,c){a=document.createElement(a);a.className=b;c&&c.appendChild(a); return a},disableTextSelection:function(){document.selection&&document.selection.empty&&document.selection.empty();if(!this._onselectstart)this._onselectstart=document.onselectstart,document.onselectstart=L.Util.falseFn},enableTextSelection:function(){document.onselectstart=this._onselectstart;this._onselectstart=null},CLASS_RE:/(\\s|^)'+cls+'(\\s|$)/,hasClass:function(a,b){return a.className.length>0&&RegExp("(^|\\s)"+b+"(\\s|$)").test(a.className)},addClass:function(a,b){L.DomUtil.hasClass(a,b)|| (a.className+=(a.className?" ":"")+b)},setOpacity:function(a,b){L.Browser.ie?a.style.filter="alpha(opacity="+Math.round(b*100)+")":a.style.opacity=b},testProp:function(a){for(var b=document.documentElement.style,c=0;c=b.lat&&a.lat<=c.lat&&d.lng>=b.lng&&a.lng<=c.lng}});L.Projection={};L.Projection.Mercator={MAX_LATITUDE:function(){var a=Math.exp(2*Math.PI);return Math.asin((a-1)/(a+1))*L.LatLng.RAD_TO_DEG}(),project:function(a){var b=L.LatLng.DEG_TO_RAD,c=L.Projection.Mercator.MAX_LATITUDE,d=a.lng*b,a=Math.max(Math.min(c,a.lat),-c)*b,a=Math.log(Math.tan(Math.PI/4+a/2));return new L.Point(d,a)},unproject:function(a,b){var c=L.LatLng.RAD_TO_DEG;return new L.LatLng((2*Math.atan(Math.exp(a.y))-Math.PI/2)*c,a.x*c,b)}};L.TileLayer=L.Class.extend({includes:L.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",opacity:1,unloadInvisibleTiles:L.Browser.mobileWebkit,updateWhenIdle:L.Browser.mobileWebkit},initialize:function(a,b){L.Util.setOptions(this,b);this._url=a;if(typeof this.options.subdomains=="string")this.options.subdomains=this.options.subdomains.split("")},onAdd:function(a){this._map=a;this._initContainer();this._tileImg=L.DomUtil.create("img","leaflet-tile"); -this._tileImg.galleryimg="no";var b=this.options.tileSize;this._tileImg.style.width=b+"px";this._tileImg.style.height=b+"px";a.on("viewreset",this._reset,this);if(this.options.updateWhenIdle)a.on("moveend",this._update,this);else this._limitedUpdate=L.Util.limitExecByInterval(this._update,100,this),a.on("move",this._limitedUpdate,this);this._reset();this._update()},onRemove:function(){this._map.getPanes().tilePane.removeChild(this._container);this._map.off("viewreset",this._reset);this.options.updateWhenIdle? -this._map.off("moveend",this._update):this._map.off("move",this._limitedUpdate)},getAttribution:function(){return this.options.attribution},_initContainer:function(){var a=this._map.getPanes().tilePane;if(!this._container||a.empty)this._container=L.DomUtil.create("div","leaflet-layer",a),this.options.opacity<1&&L.DomUtil.setOpacity(this._container,this.options.opacity)},_reset:function(){this._tiles={};this._initContainer();this._container.innerHTML=""},_update:function(){var a=this._map.getPixelBounds(), -b=this.options.tileSize,c=new L.Point(Math.floor(a.min.x/b),Math.floor(a.min.y/b)),a=new L.Point(Math.floor(a.max.x/b),Math.floor(a.max.y/b)),c=new L.Bounds(c,a);this._loadTilesFromCenterOut(c);this.options.unloadInvisibleTiles&&this._unloadOtherTiles(c)},getTileUrl:function(a,b){return this._url.replace("{s}",this.options.subdomains[(a.x+a.y)%this.options.subdomains.length]).replace("{z}",b).replace("{x}",a.x).replace("{y}",a.y)},_loadTilesFromCenterOut:function(a){for(var b=[],c=a.getCenter(),d= -a.min.y;d<=a.max.y;d++)for(var e=a.min.x;e<=a.max.x;e++)e+":"+d in this._tiles||b.push(new L.Point(e,d));b.sort(function(a,b){return a.distanceTo(c)-b.distanceTo(c)});this._tilesToLoad=b.length;a=0;for(d=this._tilesToLoad;aa.max.x||ba.max.y))this._tiles[d].parentNode==this._container&&this._container.removeChild(this._tiles[d]), -delete this._tiles[d]},_loadTile:function(a){var b=this._map.getPixelOrigin(),b=a.multiplyBy(this.options.tileSize).subtract(b),c=this._map.getZoom(),d=1<=d))d=this._tileImg.cloneNode(!1),L.DomUtil.setPosition(d,b),this._tiles[a.x+":"+a.y]=d,d._leaflet_layer=this,d.onload=this._tileOnLoad,d.onerror=this._tileOnError,d.onselectstart=d.onmousemove=L.Util.falseFn,d.src=this.getTileUrl(a,c),this._container.appendChild(d)},_tileOnLoad:function(){this.className+=" leaflet-tile-loaded"; -var a=this._leaflet_layer;a.fire("tileload",{tile:this,url:this.src});a._tilesToLoad--;a._tilesToLoad||a.fire("load")},_tileOnError:function(){this._leaflet_layer.fire("tileerror",{tile:this,url:this.src});var a=this._leaflet_layer.options.errorTileUrl;if(a)this.src=a}});L.TileLayer.WMS=L.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(a,b){this._url=a;this.wmsParams=L.Util.extend({},this.defaultWmsParams);this.wmsParams.width=this.wmsParams.height=this.options.tileSize;for(var c in b)this.options.hasOwnProperty(c)||(this.wmsParams[c]=b[c]);this.wmsParams[parseFloat(this.wmsParams.version)>=1.3?"crs":"srs"]="EPSG:3857";L.Util.setOptions(this,b)},getTileUrl:function(a){var b= -this.options.tileSize,a=a.multiplyBy(b),b=a.add(new L.Point(b,b)),a=this._map.unproject(a),b=this._map.unproject(b),a=L.Projection.Mercator.project(a).multiplyBy(6378137),b=L.Projection.Mercator.project(b).multiplyBy(6378137),b=[a.x,b.y,b.x,a.y].join(",");return this._url+L.Util.getParamString(this.wmsParams)+"&bbox="+b}});L.ImageOverlay=L.Class.extend({includes:L.Mixin.Events,initialize:function(a,b){this._url=a;this._bounds=b},onAdd:function(a){this._map=a;this._image||this._initImage();a.getPanes().overlayPane.appendChild(this._image);a.on("viewreset",this._reset,this);this._reset()},onRemove:function(a){a.getPanes().overlayPane.removeChild(this._image);a.off("viewreset",this._reset,this)},_initImage:function(){this._image=L.DomUtil.create("img","leaflet-image-layer");this._image.style.visibility="hidden";L.Util.extend(this._image, +a=a.getNorthEast()):d=a;return d.lat>=b.lat&&a.lat<=c.lat&&d.lng>=b.lng&&a.lng<=c.lng}});L.Projection={};L.Projection.Mercator={MAX_LATITUDE:function(){var a=Math.exp(2*Math.PI);return Math.asin((a-1)/(a+1))*L.LatLng.RAD_TO_DEG}(),project:function(a){var b=L.LatLng.DEG_TO_RAD,c=L.Projection.Mercator.MAX_LATITUDE,d=a.lng*b,a=Math.max(Math.min(c,a.lat),-c)*b,a=Math.log(Math.tan(Math.PI/4+a/2));return new L.Point(d,a)},unproject:function(a,b){var c=L.LatLng.RAD_TO_DEG;return new L.LatLng((2*Math.atan(Math.exp(a.y))-Math.PI/2)*c,a.x*c,b)}};L.TileLayer=L.Class.extend({includes:L.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",opacity:1,scheme:"xyz",unloadInvisibleTiles:L.Browser.mobileWebkit,updateWhenIdle:L.Browser.mobileWebkit},initialize:function(a,b){L.Util.setOptions(this,b);this._url=a;if(typeof this.options.subdomains=="string")this.options.subdomains=this.options.subdomains.split("")},onAdd:function(a){this._map=a;this._initContainer();this._createTileProto();a.on("viewreset", +this._reset,this);if(this.options.updateWhenIdle)a.on("moveend",this._update,this);else this._limitedUpdate=L.Util.limitExecByInterval(this._update,100,this),a.on("move",this._limitedUpdate,this);this._reset();this._update()},onRemove:function(){this._map.getPanes().tilePane.removeChild(this._container);this._map.off("viewreset",this._reset);this.options.updateWhenIdle?this._map.off("moveend",this._update):this._map.off("move",this._limitedUpdate)},getAttribution:function(){return this.options.attribution}, +_initContainer:function(){var a=this._map.getPanes().tilePane;if(!this._container||a.empty)this._container=L.DomUtil.create("div","leaflet-layer",a),this.options.opacity<1&&L.DomUtil.setOpacity(this._container,this.options.opacity)},_reset:function(){this._tiles={};this._initContainer();this._container.innerHTML=""},_update:function(){var a=this._map.getPixelBounds(),b=this.options.tileSize,c=new L.Point(Math.floor(a.min.x/b),Math.floor(a.min.y/b)),a=new L.Point(Math.floor(a.max.x/b),Math.floor(a.max.y/ +b)),c=new L.Bounds(c,a);this._addTilesFromCenterOut(c);this.options.unloadInvisibleTiles&&this._removeOtherTiles(c)},_addTilesFromCenterOut:function(a){for(var b=[],c=a.getCenter(),d=a.min.y;d<=a.max.y;d++)for(var e=a.min.x;e<=a.max.x;e++)e+":"+d in this._tiles||b.push(new L.Point(e,d));b.sort(function(a,b){return a.distanceTo(c)-b.distanceTo(c)});this._tilesToLoad=b.length;a=0;for(d=this._tilesToLoad;aa.max.x||ba.max.y))this._tiles[d].parentNode==this._container&&this._container.removeChild(this._tiles[d]),delete this._tiles[d]},_addTile:function(a){var b=this._getTilePos(a);zoom=this._map.getZoom();var c=1<=c||(c=this._createTile(),L.DomUtil.setPosition(c,b),this._tiles[a.x+":"+a.y]=c,this._loadTile(c,a,zoom),this._container.appendChild(c))}, +_getTilePos:function(a){var b=this._map.getPixelOrigin();return a.multiplyBy(this.options.tileSize).subtract(b)},getTileUrl:function(a,b){return this._url.replace("{s}",this.options.subdomains[(a.x+a.y)%this.options.subdomains.length]).replace("{z}",b).replace("{x}",a.x).replace("{y}",a.y)},_createTileProto:function(){this._tileImg=L.DomUtil.create("img","leaflet-tile");this._tileImg.galleryimg="no";var a=this.options.tileSize;this._tileImg.style.width=a+"px";this._tileImg.style.height=a+"px"},_createTile:function(){var a= +this._tileImg.cloneNode(!1);a.onselectstart=a.onmousemove=L.Util.falseFn;return a},_loadTile:function(a,b,c){a.onload=L.Util.bind(this._tileOnLoad,this);a.onerror=L.Util.bind(this._tileOnError,this);a.src=this.getTileUrl(b,c)},_tileOnLoad:function(a){a=L.DomEvent.getTarget(a);a.className+=" leaflet-tile-loaded";this.fire("tileload",{tile:a,url:a.src});this._tilesToLoad--;this._tilesToLoad||this.fire("load")},_tileOnError:function(a){a=L.DomEvent.getTarget(a);this.fire("tileerror",{tile:a,url:a.src}); +var b=this.options.errorTileUrl;if(b)a.src=b}});L.TileLayer.WMS=L.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(a,b){this._url=a;this.wmsParams=L.Util.extend({},this.defaultWmsParams);this.wmsParams.width=this.wmsParams.height=this.options.tileSize;for(var c in b)this.options.hasOwnProperty(c)||(this.wmsParams[c]=b[c]);this.wmsParams[parseFloat(this.wmsParams.version)>=1.3?"crs":"srs"]="EPSG:3857";L.Util.setOptions(this,b)},getTileUrl:function(a){var b= +this.options.tileSize,a=a.multiplyBy(b),b=a.add(new L.Point(b,b)),a=this._map.unproject(a),b=this._map.unproject(b),a=L.Projection.Mercator.project(a).multiplyBy(6378137),b=L.Projection.Mercator.project(b).multiplyBy(6378137),b=[a.x,b.y,b.x,a.y].join(",");return this._url+L.Util.getParamString(this.wmsParams)+"&bbox="+b}});L.TileLayer.Canvas=L.TileLayer.extend({initialize:function(a){L.Util.setOptions(this,a)},_createTileProto:function(){this._canvasProto=L.DomUtil.create("canvas","leaflet-tile");var a=this.options.tileSize;this._canvasProto.width=a;this._canvasProto.height=a},_createTile:function(){var a=this._canvasProto.cloneNode(!1);a.onselectstart=a.onmousemove=L.Util.falseFn;return a},_loadTile:function(a,b,c){this.drawTile(a,b,c);this._tileOnLoad({target:a})},drawTile:function(){}});L.ImageOverlay=L.Class.extend({includes:L.Mixin.Events,initialize:function(a,b){this._url=a;this._bounds=b},onAdd:function(a){this._map=a;this._image||this._initImage();a.getPanes().overlayPane.appendChild(this._image);a.on("viewreset",this._reset,this);this._reset()},onRemove:function(a){a.getPanes().overlayPane.removeChild(this._image);a.off("viewreset",this._reset,this)},_initImage:function(){this._image=L.DomUtil.create("img","leaflet-image-layer");this._image.style.visibility="hidden";L.Util.extend(this._image, {galleryimg:"no",onselectstart:L.Util.falseFn,onmousemove:L.Util.falseFn,onload:this._onImageLoad,src:this._url})},_reset:function(){var a=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),b=this._map.latLngToLayerPoint(this._bounds.getSouthEast()).subtract(a);L.DomUtil.setPosition(this._image,a);this._image.style.width=b.x+"px";this._image.style.height=b.y+"px"},_onImageLoad:function(){this.style.visibility=""}});L.Popup=L.Class.extend({includes:L.Mixin.Events,options:{maxWidth:300,autoPan:!0,closeButton:!0,offset:new L.Point(0,2),autoPanPadding:new L.Point(5,5)},initialize:function(a){L.Util.setOptions(this,a)},onAdd:function(a){this._map=a;this._container||this._initLayout();this._updateContent();this._container.style.opacity="0";this._map._panes.popupPane.appendChild(this._container);this._map.on("viewreset",this._updatePosition,this);if(this._map.options.closePopupOnClick)this._map.on("preclick",this._close, this);this._update();this._container.style.opacity="1";this._opened=!0},onRemove:function(a){a._panes.popupPane.removeChild(this._container);a.off("viewreset",this._updatePosition,this);a.off("click",this._close,this);this._container.style.opacity="0";this._opened=!1},setLatLng:function(a){this._latlng=a;this._opened&&this._update();return this},setContent:function(a){this._content=a;this._opened&&this._update();return this},_close:function(){this._opened&&this._map.removeLayer(this)},_initLayout:function(){this._container= L.DomUtil.create("div","leaflet-popup");this._closeButton=L.DomUtil.create("a","leaflet-popup-close-button",this._container);this._closeButton.href="#close";this._closeButton.onclick=L.Util.bind(this._onCloseButtonClick,this);this._wrapper=L.DomUtil.create("div","leaflet-popup-content-wrapper",this._container);L.DomEvent.disableClickPropagation(this._wrapper);this._contentNode=L.DomUtil.create("div","leaflet-popup-content",this._wrapper);this._tipContainer=L.DomUtil.create("div","leaflet-popup-tip-container", diff --git a/src/dom/DomEvent.js b/src/dom/DomEvent.js index a07e9f60..c185de88 100644 --- a/src/dom/DomEvent.js +++ b/src/dom/DomEvent.js @@ -106,6 +106,16 @@ L.DomEvent = { } }, + getTarget: function(e) { + var target = e.target || e.srcElement; + + if (target && target.nodeType == 3) { + target = target.parentNode; + } + + return target; + }, + getMousePosition: function(e, container) { var x = e.pageX ? e.pageX : e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft, diff --git a/src/layer/tile/TileLayer.Canvas.js b/src/layer/tile/TileLayer.Canvas.js new file mode 100644 index 00000000..a3d3833b --- /dev/null +++ b/src/layer/tile/TileLayer.Canvas.js @@ -0,0 +1,28 @@ +L.TileLayer.Canvas = L.TileLayer.extend({ + initialize: function(options) { + L.Util.setOptions(this, options); + }, + + _createTileProto: function() { + this._canvasProto = L.DomUtil.create('canvas', 'leaflet-tile'); + + var tileSize = this.options.tileSize; + this._canvasProto.width = tileSize; + this._canvasProto.height = tileSize; + }, + + _createTile: function() { + var tile = this._canvasProto.cloneNode(false); + tile.onselectstart = tile.onmousemove = L.Util.falseFn; + return tile; + }, + + _loadTile: function(tile, tilePoint, zoom) { + this.drawTile(tile, tilePoint, zoom); + this._tileOnLoad({target: tile}); + }, + + drawTile: function(tile, tilePoint, zoom) { + // override with rendering code + } +}); \ No newline at end of file diff --git a/src/layer/TileLayer.WMS.js b/src/layer/tile/TileLayer.WMS.js similarity index 100% rename from src/layer/TileLayer.WMS.js rename to src/layer/tile/TileLayer.WMS.js diff --git a/src/layer/TileLayer.js b/src/layer/tile/TileLayer.js similarity index 73% rename from src/layer/TileLayer.js rename to src/layer/tile/TileLayer.js index e1f3f96e..57f9b2fc 100644 --- a/src/layer/TileLayer.js +++ b/src/layer/tile/TileLayer.js @@ -13,6 +13,7 @@ L.TileLayer = L.Class.extend({ errorTileUrl: '', attribution: '', opacity: 1, + scheme: 'xyz', unloadInvisibleTiles: L.Browser.mobileWebkit, updateWhenIdle: L.Browser.mobileWebkit @@ -35,12 +36,7 @@ L.TileLayer = L.Class.extend({ this._initContainer(); // create an image to clone for tiles - this._tileImg = L.DomUtil.create('img', 'leaflet-tile'); - this._tileImg.galleryimg = 'no'; - - var tileSize = this.options.tileSize; - this._tileImg.style.width = tileSize + 'px'; - this._tileImg.style.height = tileSize + 'px'; + this._createTileProto(); // set up events map.on('viewreset', this._reset, this); @@ -102,25 +98,14 @@ L.TileLayer = L.Class.extend({ Math.floor(bounds.max.y / tileSize)), tileBounds = new L.Bounds(nwTilePoint, seTilePoint); - this._loadTilesFromCenterOut(tileBounds); + this._addTilesFromCenterOut(tileBounds); if (this.options.unloadInvisibleTiles) { - this._unloadOtherTiles(tileBounds); + this._removeOtherTiles(tileBounds); } }, - getTileUrl: function(tilePoint, zoom) { - var subdomains = this.options.subdomains, - s = this.options.subdomains[(tilePoint.x + tilePoint.y) % subdomains.length]; - - return this._url - .replace('{s}', s) - .replace('{z}', zoom) - .replace('{x}', tilePoint.x) - .replace('{y}', tilePoint.y); - }, - - _loadTilesFromCenterOut: function(bounds) { + _addTilesFromCenterOut: function(bounds) { var queue = [], center = bounds.getCenter(); @@ -138,11 +123,11 @@ L.TileLayer = L.Class.extend({ this._tilesToLoad = queue.length; for (var k = 0, len = this._tilesToLoad; k < len; k++) { - this._loadTile(queue[k]); + this._addTile(queue[k]); } }, - _unloadOtherTiles: function(bounds) { + _removeOtherTiles: function(bounds) { var kArr, x, y, key; for (key in this._tiles) { @@ -162,54 +147,89 @@ L.TileLayer = L.Class.extend({ } }, - _loadTile: function(tilePoint) { - var origin = this._map.getPixelOrigin(), - tileSize = this.options.tileSize, - tilePos = tilePoint.multiplyBy(tileSize).subtract(origin), + _addTile: function(tilePoint) { + var tilePos = this._getTilePos(tilePoint); zoom = this._map.getZoom(); // wrap tile coordinates var tileLimit = (1 << zoom); tilePoint.x = ((tilePoint.x % tileLimit) + tileLimit) % tileLimit; + if (this.options.scheme == 'tms') tilePoint.y = tileLimit - tilePoint.y - 1; if (tilePoint.y < 0 || tilePoint.y >= tileLimit) { return; } // create tile - var tile = this._tileImg.cloneNode(false); - + var tile = this._createTile(); L.DomUtil.setPosition(tile, tilePos); this._tiles[tilePoint.x + ':' + tilePoint.y] = tile; - tile._leaflet_layer = this; - tile.onload = this._tileOnLoad; - tile.onerror = this._tileOnError; - tile.onselectstart = tile.onmousemove = L.Util.falseFn; - - tile.src = this.getTileUrl(tilePoint, zoom); + this._loadTile(tile, tilePoint, zoom); this._container.appendChild(tile); }, - _tileOnLoad: function() { - this.className += ' leaflet-tile-loaded'; //TODO DomEvent#addListener target + _getTilePos: function(tilePoint) { + var origin = this._map.getPixelOrigin(), + tileSize = this.options.tileSize; + + return tilePoint.multiplyBy(tileSize).subtract(origin); + }, + + // image-specific code (override to implement e.g. Canvas or SVG tile layer) + + getTileUrl: function(tilePoint, zoom) { + var subdomains = this.options.subdomains, + s = this.options.subdomains[(tilePoint.x + tilePoint.y) % subdomains.length]; - var layer = this._leaflet_layer; + return this._url + .replace('{s}', s) + .replace('{z}', zoom) + .replace('{x}', tilePoint.x) + .replace('{y}', tilePoint.y); + }, + + _createTileProto: function() { + this._tileImg = L.DomUtil.create('img', 'leaflet-tile'); + this._tileImg.galleryimg = 'no'; - layer.fire('tileload', {tile: this, url: this.src}); + var tileSize = this.options.tileSize; + this._tileImg.style.width = tileSize + 'px'; + this._tileImg.style.height = tileSize + 'px'; + }, + + _createTile: function() { + var tile = this._tileImg.cloneNode(false); + tile.onselectstart = tile.onmousemove = L.Util.falseFn; + return tile; + }, + + _loadTile: function(tile, tilePoint, zoom) { + tile.onload = L.Util.bind(this._tileOnLoad, this); + tile.onerror = L.Util.bind(this._tileOnError, this); + tile.src = this.getTileUrl(tilePoint, zoom); + }, + + _tileOnLoad: function(e) { + var tile = L.DomEvent.getTarget(e); - layer._tilesToLoad--; - if (!layer._tilesToLoad) { - layer.fire('load'); + tile.className += ' leaflet-tile-loaded'; + + this.fire('tileload', {tile: tile, url: tile.src}); + + this._tilesToLoad--; + if (!this._tilesToLoad) { + this.fire('load'); } }, - _tileOnError: function() { - this._leaflet_layer.fire('tileerror', {tile: this, url: this.src}); + _tileOnError: function(e) { + var tile = L.DomEvent.getTarget(e); - var newUrl = this._leaflet_layer.options.errorTileUrl; + this.fire('tileerror', {tile: tile, url: tile.src}); + + var newUrl = this.options.errorTileUrl; if (newUrl) { - this.src = newUrl; + tile.src = newUrl; } - } -}); \ No newline at end of file +});