diff --git a/dist/virtual-grid.js b/dist/virtual-grid.js new file mode 100644 index 0000000..8ddbc9d --- /dev/null +++ b/dist/virtual-grid.js @@ -0,0 +1,306 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('leaflet')) : + typeof define === 'function' && define.amd ? define(['leaflet'], factory) : + global.VirtualGrid = factory(global.leaflet); +}(this, function (leaflet) { 'use strict'; + + var VirtualGrid = leaflet.Layer.extend({ + + options: { + cellSize: 512, + updateInterval: 150 + }, + + initialize: function (options) { + options = leaflet.setOptions(this, options); + this._zooming = false; + }, + + onAdd: function (map) { + this._map = map; + this._update = leaflet.Util.throttle(this._update, this.options.updateInterval, this); + this._reset(); + this._update(); + }, + + onRemove: function () { + this._map.removeEventListener(this.getEvents(), this); + this._removeCells(); + }, + + getEvents: function () { + var events = { + moveend: this._update, + zoomstart: this._zoomstart, + zoomend: this._reset + }; + + return events; + }, + + addTo: function (map) { + map.addLayer(this); + return this; + }, + + removeFrom: function (map) { + map.removeLayer(this); + return this; + }, + + _zoomstart: function () { + this._zooming = true; + }, + + _reset: function () { + this._removeCells(); + + this._cells = {}; + this._activeCells = {}; + this._cellsToLoad = 0; + this._cellsTotal = 0; + this._cellNumBounds = this._getCellNumBounds(); + + this._resetWrap(); + this._zooming = false; + }, + + _resetWrap: function () { + var map = this._map; + var crs = map.options.crs; + + if (crs.infinite) { return; } + + var cellSize = this._getCellSize(); + + if (crs.wrapLng) { + this._wrapLng = [ + Math.floor(map.project([0, crs.wrapLng[0]]).x / cellSize), + Math.ceil(map.project([0, crs.wrapLng[1]]).x / cellSize) + ]; + } + + if (crs.wrapLat) { + this._wrapLat = [ + Math.floor(map.project([crs.wrapLat[0], 0]).y / cellSize), + Math.ceil(map.project([crs.wrapLat[1], 0]).y / cellSize) + ]; + } + }, + + _getCellSize: function () { + return this.options.cellSize; + }, + + _update: function () { + if (!this._map) { + return; + } + + var mapBounds = this._map.getPixelBounds(); + var cellSize = this._getCellSize(); + + // cell coordinates range for the current view + var cellBounds = leaflet.bounds( + mapBounds.min.divideBy(cellSize).floor(), + mapBounds.max.divideBy(cellSize).floor()); + + this._removeOtherCells(cellBounds); + this._addCells(cellBounds); + + this.fire('cellsupdated'); + }, + + _addCells: function (cellBounds) { + var queue = []; + var center = cellBounds.getCenter(); + var zoom = this._map.getZoom(); + + var j, i, coords; + // create a queue of coordinates to load cells from + for (j = cellBounds.min.y; j <= cellBounds.max.y; j++) { + for (i = cellBounds.min.x; i <= cellBounds.max.x; i++) { + coords = leaflet.point(i, j); + coords.z = zoom; + + if (this._isValidCell(coords)) { + queue.push(coords); + } + } + } + + var cellsToLoad = queue.length; + + if (cellsToLoad === 0) { return; } + + this._cellsToLoad += cellsToLoad; + this._cellsTotal += cellsToLoad; + + // sort cell queue to load cells in order of their distance to center + queue.sort(function (a, b) { + return a.distanceTo(center) - b.distanceTo(center); + }); + + for (i = 0; i < cellsToLoad; i++) { + this._addCell(queue[i]); + } + }, + + _isValidCell: function (coords) { + var crs = this._map.options.crs; + + if (!crs.infinite) { + // don't load cell if it's out of bounds and not wrapped + var cellNumBounds = this._cellNumBounds; + + if (!cellNumBounds) return false; + if ( + (!crs.wrapLng && (coords.x < cellNumBounds.min.x || coords.x > cellNumBounds.max.x)) || + (!crs.wrapLat && (coords.y < cellNumBounds.min.y || coords.y > cellNumBounds.max.y)) + ) { + return false; + } + } + + if (!this.options.bounds) { + return true; + } + + // don't load cell if it doesn't intersect the bounds in options + var cellBounds = this._cellCoordsToBounds(coords); + return leaflet.latLngBounds(this.options.bounds).intersects(cellBounds); + }, + + // converts cell coordinates to its geographical bounds + _cellCoordsToBounds: function (coords) { + var map = this._map; + var cellSize = this.options.cellSize; + var nwPoint = coords.multiplyBy(cellSize); + var sePoint = nwPoint.add([cellSize, cellSize]); + var nw = map.wrapLatLng(map.unproject(nwPoint, coords.z)); + var se = map.wrapLatLng(map.unproject(sePoint, coords.z)); + + return leaflet.latLngBounds(nw, se); + }, + + // converts cell coordinates to key for the cell cache + _cellCoordsToKey: function (coords) { + return coords.x + ':' + coords.y; + }, + + // converts cell cache key to coordiantes + _keyToCellCoords: function (key) { + var kArr = key.split(':'); + var x = parseInt(kArr[0], 10); + var y = parseInt(kArr[1], 10); + + return leaflet.point(x, y); + }, + + // remove any present cells that are off the specified bounds + _removeOtherCells: function (bounds) { + for (var key in this._cells) { + if (!bounds.contains(this._keyToCellCoords(key))) { + this._removeCell(key); + } + } + }, + + _removeCell: function (key) { + var cell = this._activeCells[key]; + + if (cell) { + delete this._activeCells[key]; + + if (this.cellLeave) { + this.cellLeave(cell.bounds, cell.coords); + } + + this.fire('cellleave', { + bounds: cell.bounds, + coords: cell.coords + }); + } + }, + + _removeCells: function () { + for (var key in this._cells) { + var cellBounds = this._cells[key].bounds; + var coords = this._cells[key].coords; + + if (this.cellLeave) { + this.cellLeave(cellBounds, coords); + } + + this.fire('cellleave', { + bounds: cellBounds, + coords: coords + }); + } + }, + + _addCell: function (coords) { + // wrap cell coords if necessary (depending on CRS) + this._wrapCoords(coords); + + // generate the cell key + var key = this._cellCoordsToKey(coords); + + // get the cell from the cache + var cell = this._cells[key]; + // if this cell should be shown as isnt active yet (enter) + + if (cell && !this._activeCells[key]) { + if (this.cellEnter) { + this.cellEnter(cell.bounds, coords); + } + + this.fire('cellenter', { + bounds: cell.bounds, + coords: coords + }); + + this._activeCells[key] = cell; + } + + // if we dont have this cell in the cache yet (create) + if (!cell) { + cell = { + coords: coords, + bounds: this._cellCoordsToBounds(coords) + }; + + this._cells[key] = cell; + this._activeCells[key] = cell; + + if (this.createCell) { + this.createCell(cell.bounds, coords); + } + + this.fire('cellcreate', { + bounds: cell.bounds, + coords: coords + }); + } + }, + + _wrapCoords: function (coords) { + coords.x = this._wrapLng ? leaflet.Util.wrapNum(coords.x, this._wrapLng) : coords.x; + coords.y = this._wrapLat ? leaflet.Util.wrapNum(coords.y, this._wrapLat) : coords.y; + }, + + // get the global cell coordinates range for the current zoom + _getCellNumBounds: function () { + var worldBounds = this._map.getPixelWorldBounds(); + var size = this._getCellSize(); + + return worldBounds ? leaflet.bounds( + worldBounds.min.divideBy(size).floor(), + worldBounds.max.divideBy(size).ceil().subtract([1, 1])) : null; + } + }); + + return VirtualGrid; + +})); +//# sourceMappingURL=virtual-grid.js.map \ No newline at end of file diff --git a/dist/virtual-grid.js.map b/dist/virtual-grid.js.map new file mode 100644 index 0000000..7ad1043 --- /dev/null +++ b/dist/virtual-grid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"virtual-grid.js","sources":["..//Users/john6251/github/leaflet-virtual-grid/src/virtual-grid.js"],"sourcesContent":["import {\n bounds,\n latLngBounds,\n point,\n Layer,\n setOptions,\n Util\n} from 'leaflet';\n\nvar VirtualGrid = Layer.extend({\n\n options: {\n cellSize: 512,\n updateInterval: 150\n },\n\n initialize: function (options) {\n options = setOptions(this, options);\n this._zooming = false;\n },\n\n onAdd: function (map) {\n this._map = map;\n this._update = Util.throttle(this._update, this.options.updateInterval, this);\n this._reset();\n this._update();\n },\n\n onRemove: function () {\n this._map.removeEventListener(this.getEvents(), this);\n this._removeCells();\n },\n\n getEvents: function () {\n var events = {\n moveend: this._update,\n zoomstart: this._zoomstart,\n zoomend: this._reset\n };\n\n return events;\n },\n\n addTo: function (map) {\n map.addLayer(this);\n return this;\n },\n\n removeFrom: function (map) {\n map.removeLayer(this);\n return this;\n },\n\n _zoomstart: function () {\n this._zooming = true;\n },\n\n _reset: function () {\n this._removeCells();\n\n this._cells = {};\n this._activeCells = {};\n this._cellsToLoad = 0;\n this._cellsTotal = 0;\n this._cellNumBounds = this._getCellNumBounds();\n\n this._resetWrap();\n this._zooming = false;\n },\n\n _resetWrap: function () {\n var map = this._map;\n var crs = map.options.crs;\n\n if (crs.infinite) { return; }\n\n var cellSize = this._getCellSize();\n\n if (crs.wrapLng) {\n this._wrapLng = [\n Math.floor(map.project([0, crs.wrapLng[0]]).x / cellSize),\n Math.ceil(map.project([0, crs.wrapLng[1]]).x / cellSize)\n ];\n }\n\n if (crs.wrapLat) {\n this._wrapLat = [\n Math.floor(map.project([crs.wrapLat[0], 0]).y / cellSize),\n Math.ceil(map.project([crs.wrapLat[1], 0]).y / cellSize)\n ];\n }\n },\n\n _getCellSize: function () {\n return this.options.cellSize;\n },\n\n _update: function () {\n if (!this._map) {\n return;\n }\n\n var mapBounds = this._map.getPixelBounds();\n var cellSize = this._getCellSize();\n\n // cell coordinates range for the current view\n var cellBounds = bounds(\n mapBounds.min.divideBy(cellSize).floor(),\n mapBounds.max.divideBy(cellSize).floor());\n\n this._removeOtherCells(cellBounds);\n this._addCells(cellBounds);\n\n this.fire('cellsupdated');\n },\n\n _addCells: function (cellBounds) {\n var queue = [];\n var center = cellBounds.getCenter();\n var zoom = this._map.getZoom();\n\n var j, i, coords;\n // create a queue of coordinates to load cells from\n for (j = cellBounds.min.y; j <= cellBounds.max.y; j++) {\n for (i = cellBounds.min.x; i <= cellBounds.max.x; i++) {\n coords = point(i, j);\n coords.z = zoom;\n\n if (this._isValidCell(coords)) {\n queue.push(coords);\n }\n }\n }\n\n var cellsToLoad = queue.length;\n\n if (cellsToLoad === 0) { return; }\n\n this._cellsToLoad += cellsToLoad;\n this._cellsTotal += cellsToLoad;\n\n // sort cell queue to load cells in order of their distance to center\n queue.sort(function (a, b) {\n return a.distanceTo(center) - b.distanceTo(center);\n });\n\n for (i = 0; i < cellsToLoad; i++) {\n this._addCell(queue[i]);\n }\n },\n\n _isValidCell: function (coords) {\n var crs = this._map.options.crs;\n\n if (!crs.infinite) {\n // don't load cell if it's out of bounds and not wrapped\n var cellNumBounds = this._cellNumBounds;\n\n if (!cellNumBounds) return false;\n if (\n (!crs.wrapLng && (coords.x < cellNumBounds.min.x || coords.x > cellNumBounds.max.x)) ||\n (!crs.wrapLat && (coords.y < cellNumBounds.min.y || coords.y > cellNumBounds.max.y))\n ) {\n return false;\n }\n }\n\n if (!this.options.bounds) {\n return true;\n }\n\n // don't load cell if it doesn't intersect the bounds in options\n var cellBounds = this._cellCoordsToBounds(coords);\n return latLngBounds(this.options.bounds).intersects(cellBounds);\n },\n\n // converts cell coordinates to its geographical bounds\n _cellCoordsToBounds: function (coords) {\n var map = this._map;\n var cellSize = this.options.cellSize;\n var nwPoint = coords.multiplyBy(cellSize);\n var sePoint = nwPoint.add([cellSize, cellSize]);\n var nw = map.wrapLatLng(map.unproject(nwPoint, coords.z));\n var se = map.wrapLatLng(map.unproject(sePoint, coords.z));\n\n return latLngBounds(nw, se);\n },\n\n // converts cell coordinates to key for the cell cache\n _cellCoordsToKey: function (coords) {\n return coords.x + ':' + coords.y;\n },\n\n // converts cell cache key to coordiantes\n _keyToCellCoords: function (key) {\n var kArr = key.split(':');\n var x = parseInt(kArr[0], 10);\n var y = parseInt(kArr[1], 10);\n\n return point(x, y);\n },\n\n // remove any present cells that are off the specified bounds\n _removeOtherCells: function (bounds) {\n for (var key in this._cells) {\n if (!bounds.contains(this._keyToCellCoords(key))) {\n this._removeCell(key);\n }\n }\n },\n\n _removeCell: function (key) {\n var cell = this._activeCells[key];\n\n if (cell) {\n delete this._activeCells[key];\n\n if (this.cellLeave) {\n this.cellLeave(cell.bounds, cell.coords);\n }\n\n this.fire('cellleave', {\n bounds: cell.bounds,\n coords: cell.coords\n });\n }\n },\n\n _removeCells: function () {\n for (var key in this._cells) {\n var cellBounds = this._cells[key].bounds;\n var coords = this._cells[key].coords;\n\n if (this.cellLeave) {\n this.cellLeave(cellBounds, coords);\n }\n\n this.fire('cellleave', {\n bounds: cellBounds,\n coords: coords\n });\n }\n },\n\n _addCell: function (coords) {\n // wrap cell coords if necessary (depending on CRS)\n this._wrapCoords(coords);\n\n // generate the cell key\n var key = this._cellCoordsToKey(coords);\n\n // get the cell from the cache\n var cell = this._cells[key];\n // if this cell should be shown as isnt active yet (enter)\n\n if (cell && !this._activeCells[key]) {\n if (this.cellEnter) {\n this.cellEnter(cell.bounds, coords);\n }\n\n this.fire('cellenter', {\n bounds: cell.bounds,\n coords: coords\n });\n\n this._activeCells[key] = cell;\n }\n\n // if we dont have this cell in the cache yet (create)\n if (!cell) {\n cell = {\n coords: coords,\n bounds: this._cellCoordsToBounds(coords)\n };\n\n this._cells[key] = cell;\n this._activeCells[key] = cell;\n\n if (this.createCell) {\n this.createCell(cell.bounds, coords);\n }\n\n this.fire('cellcreate', {\n bounds: cell.bounds,\n coords: coords\n });\n }\n },\n\n _wrapCoords: function (coords) {\n coords.x = this._wrapLng ? Util.wrapNum(coords.x, this._wrapLng) : coords.x;\n coords.y = this._wrapLat ? Util.wrapNum(coords.y, this._wrapLat) : coords.y;\n },\n\n // get the global cell coordinates range for the current zoom\n _getCellNumBounds: function () {\n var worldBounds = this._map.getPixelWorldBounds();\n var size = this._getCellSize();\n\n return worldBounds ? bounds(\n worldBounds.min.divideBy(size).floor(),\n worldBounds.max.divideBy(size).ceil().subtract([1, 1])) : null;\n }\n});\n\nexport default VirtualGrid;\n"],"names":["Layer","setOptions","Util","bounds","point","latLngBounds"],"mappings":"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"} \ No newline at end of file