UNPKG

mapv

Version:

a library of geography visualization

231 lines (192 loc) 6.45 kB
if(typeof(L) !== 'undefined') { /** * full canvas layer implementation for Leaflet */ L.CanvasLayer = L.Class.extend({ includes: [L.Mixin.Events, L.Mixin.TileLoader], options: { minZoom: 0, maxZoom: 28, tileSize: 256, subdomains: 'abc', errorTileUrl: '', attribution: '', zoomOffset: 0, opacity: 1, unloadInvisibleTiles: L.Browser.mobile, updateWhenIdle: L.Browser.mobile, tileLoader: false // installs tile loading events }, initialize: function (options) { var self = this; options = options || {}; //this.project = this._project.bind(this); this.render = this.render.bind(this); L.Util.setOptions(this, options); this._canvas = this._createCanvas(); // backCanvas for zoom animation this._backCanvas = this._createCanvas(); this._ctx = this._canvas.getContext('2d'); this.currentAnimationFrame = -1; this.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { return window.setTimeout(callback, 1000 / 60); }; this.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || function(id) { clearTimeout(id); }; }, _createCanvas: function() { var canvas; canvas = document.createElement('canvas'); canvas.style.position = 'absolute'; canvas.style.top = 0; canvas.style.left = 0; canvas.style.pointerEvents = "none"; canvas.style.zIndex = this.options.zIndex || 0; var className = 'leaflet-tile-container leaflet-zoom-animated'; canvas.setAttribute('class', className); return canvas; }, onAdd: function (map) { this._map = map; // add container with the canvas to the tile pane // the container is moved in the oposite direction of the // map pane to keep the canvas always in (0, 0) var tilePane = this._map._panes.tilePane; var _container = L.DomUtil.create('div', 'leaflet-layer'); _container.appendChild(this._canvas); _container.appendChild(this._backCanvas); this._backCanvas.style.display = 'none'; tilePane.appendChild(_container); this._container = _container; // hack: listen to predrag event launched by dragging to // set container in position (0, 0) in screen coordinates if (map.dragging.enabled()) { map.dragging._draggable.on('predrag', function() { var d = map.dragging._draggable; L.DomUtil.setPosition(this._canvas, { x: -d._newPos.x, y: -d._newPos.y }); }, this); } map.on({ 'viewreset': this._reset }, this); map.on('move', this.redraw, this); map.on('resize', this._reset, this); map.on({ 'zoomanim': this._animateZoom, 'zoomend': this._endZoomAnim }, this); if(this.options.tileLoader) { this._initTileLoader(); } this._reset(); }, _animateZoom: function (e) { if (!this._animating) { this._animating = true; } var back = this._backCanvas; back.width = this._canvas.width; back.height = this._canvas.height; // paint current canvas in back canvas with trasnformation var pos = this._canvas._leaflet_pos || { x: 0, y: 0 }; back.getContext('2d').drawImage(this._canvas, 0, 0); // hide original this._canvas.style.display = 'none'; back.style.display = 'block'; var map = this._map; var scale = map.getZoomScale(e.zoom); var newCenter = map._latLngToNewLayerPoint(map.getCenter(), e.zoom, e.center); var oldCenter = map._latLngToNewLayerPoint(e.center, e.zoom, e.center); var origin = { x: newCenter.x - oldCenter.x, y: newCenter.y - oldCenter.y }; var bg = back; var transform = L.DomUtil.TRANSFORM; bg.style[transform] = L.DomUtil.getTranslateString(origin) + ' scale(' + e.scale + ') '; }, _endZoomAnim: function () { this._animating = false; this._canvas.style.display = 'block'; this._backCanvas.style.display = 'none'; }, getCanvas: function() { return this._canvas; }, getAttribution: function() { return this.options.attribution; }, draw: function() { return this._reset(); }, onRemove: function (map) { this._container.parentNode.removeChild(this._container); map.off({ 'viewreset': this._reset, 'move': this._render, 'resize': this._reset, 'zoomanim': this._animateZoom, 'zoomend': this._endZoomAnim }, this); }, addTo: function (map) { map.addLayer(this); return this; }, setOpacity: function (opacity) { this.options.opacity = opacity; this._updateOpacity(); return this; }, setZIndex: function(zIndex) { this._canvas.style.zIndex = zIndex; }, bringToFront: function () { return this; }, bringToBack: function () { return this; }, _reset: function () { var size = this._map.getSize(); this._canvas.width = size.x; this._canvas.height = size.y; // fix position var pos = L.DomUtil.getPosition(this._map.getPanes().mapPane); if (pos) { L.DomUtil.setPosition(this._canvas, { x: -pos.x, y: -pos.y }); } this.onResize(); this._render(); }, /* _project: function(x) { var point = this._map.latLngToLayerPoint(new L.LatLng(x[1], x[0])); return [point.x, point.y]; }, */ _updateOpacity: function () { }, _render: function() { if (this.currentAnimationFrame >= 0) { this.cancelAnimationFrame.call(window, this.currentAnimationFrame); } this.currentAnimationFrame = this.requestAnimationFrame.call(window, this.render); }, // use direct: true if you are inside an animation frame call redraw: function(direct) { var domPosition = L.DomUtil.getPosition(this._map.getPanes().mapPane); if (domPosition) { L.DomUtil.setPosition(this._canvas, { x: -domPosition.x, y: -domPosition.y }); } if (direct) { this.render(); } else { this._render(); } }, onResize: function() { }, render: function() { throw new Error('render function should be implemented'); } }); } //L defined