ngx.leaflet.offline
Version:
A Leaflet library that downloads map tiles and uses them offline.
143 lines (108 loc) • 8.15 kB
Markdown
# ngx.leaflet.offline [](https://opensource.org/licenses/GPL-2.0) [](https://badge.fury.io/js/ngx.leaflet.offline)
A Leaflet library that downloads map tiles and uses them offline.
Check out the demo at https://betoxl.github.io/ngx.leaflet.offline/index.html .
Example: https://github.com/BETOXL/offlinemap-angular-example
@types https://www.npmjs.com/package/@types/ngx.leaflet.offline
## Inspiration
This library was heavily inspired and based on the [leaflet.offline](https://github.com/allartk/leaflet.offline) library by Allart Kooiman.
I decided to create a new one because the ideas I had were diverging too much from what ```leaflet.offline``` proposes to do.
The biggest change I made was removing the dependency on [localForage](https://github.com/localForage/localForage) and introducing a new parameter that makes you able to give your own implementantion of a database layer to save, retrieve and delete the map tiles however you like as long as it implements the same interface (more on that below).
## Dependencies
- [Leaflet](https://github.com/Leaflet/Leaflet) (v1.1.0)
## Install
If you use ```npm```, you can install ```ngx.leaflet.offline``` by running:
```npm install ngx.leaflet.offline```
If you don't use a package manager, simply download a file from the ```dist/``` folder and include it in your application.
## Guide
### Database Layer
When creating both the ```OfflineControl``` and the ```OfflineLayer```, you need to pass an object that will act as the database layer when saving, retrieving and deleting map tiles.
The object **must** implement the following interface.
| Method | Parameters | Returns |
| ----------- | --------------- | --------------------------------------------------------------------------------------------- |
| 'getItem' | key: String | Promise. The result of the promise must be a Blob, File or MediaStream representing the image |
| 'saveTiles' | tileUrls: Array | Promise. The result is ignored |
| 'clear' | None | Promise. The result is ignored |
### Layer API
When creating the ```OfflineLayer```, you need to pass the URL from where the map tiles will be retrieved, the database layer object and the options parameter.
There are no special options for the ```OfflineLayer```, they are the same as the [TileLayer options](http://leafletjs.com/reference-1.2.0.html#tilelayer-option) from Leaflet.
### Control API
When creating the ```OfflineControl```, you need to pass the ```OfflineLayer```, the database layer object and the options parameter.
The options parameter is defined as follows:
| Option | Type | Default | Description |
| ------------------------ | -------- | -------------- | ---------------------------------------------------------------------------------- |
| 'position' | String | 'topleft' | [Control options](http://leafletjs.com/reference-1.2.0.html#control-position) |
| 'saveButtonHtml' | String | 'S' | The HTML that will be displayed as the save button |
| 'saveButtonTitle' | String | 'Save tiles' | The title that will be used for the save button |
| 'removeButtonHtml' | String | 'R' | The HTML that will be displayed as the remove button |
| 'removeButtonTitle' | String | 'Remove tiles' | The title that will be used for the remove button |
| 'minZoom' | Number | 0 | The save operation won't start when trying to save map tiles below this zoom level |
| 'maxZoom' | Number | 19 | The save operation will not save map tiles beyond this zoom level |
| 'confirmSavingCallback' | Function | null | A function to be executed before the save operation starts |
| 'confirmRemovalCallback' | Function | null | A function to be executed before the remove operation starts |
The callbacks should implement the following interface.
| Method | Parameters | Returns |
| ------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------- |
| 'confirmSavingCallback' | nTilesToSave: Number, continueSaveTiles: Function | Whatever. Remember to call ```continueSaveTiles``` to resume the operation |
| 'confirmRemovalCallback' | continueRemoveTiles: Function | Whatever. Remember to call ```continueRemoveTiles``` to resume the operation |
### Events
Events fired by the ```OfflineControl``` on the ```OfflineLayer```. Assume that ```tilesDb``` is the database layer object.
| Event | Data | Description |
| ------------------------------ | ---------------------- | ------------------------------------------------------------------------------- |
| 'offline:below-min-zoom-error' | undefined | Fired when trying to save below minimum zoom level |
| 'offline:save-start' | {nTilesToSave: Number} | Fired when the save operation starts but before calling ```tilesDb.saveTiles``` |
| 'offline:save-end' | undefined | Fired when the promise from ```tilesDb.saveTiles``` finishes successfully |
| 'offline:save-error' | {error: Error} | Fired when the promise from ```tilesDb.saveTiles``` finishes with an error |
| 'offline:remove-start' | undefined | Fired when the remove operation starts but before calling ```tilesDb.clear``` |
| 'offline:remove-end' | undefined | Fired when the promise from ```tilesDb.clear``` finishes successfully |
| 'offline:remove-error' | {error: Error} | Fired when the promise from ```tilesDb.clear``` finishes with an error |
## Example
Creating the database layer object.
```javascript
var tilesDb = {
getItem: function (key) {
// return Promise that has the image Blob/File/Stream.
},
saveTiles: function (tileUrls) {
// return Promise.
},
clear: function () {
// return Promise.
}
};
```
Creating the ```OfflineLayer```.
```javascript
var map = L.map('map-id');
var offlineLayer = L.tileLayer.offline('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', tilesDb, {
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
subdomains: 'abc',
minZoom: 13,
maxZoom: 19,
crossOrigin: true
});
```
Creating the ```OfflineControl```.
```javascript
var offlineControl = L.control.offline(offlineLayer, tilesDb, {
saveButtonHtml: '<i class="fa fa-download" aria-hidden="true"></i>',
removeButtonHtml: '<i class="fa fa-trash" aria-hidden="true"></i>',
confirmSavingCallback: function (nTilesToSave, continueSaveTiles) {
if (window.confirm('Save ' + nTilesToSave + '?')) {
continueSaveTiles();
}
},
confirmRemovalCallback: function (continueRemoveTiles) {
if (window.confirm('Remove all the tiles?')) {
continueRemoveTiles();
}
},
minZoom: 13,
maxZoom: 19
});
```
Adding both of them to the map.
```javascript
offlineLayer.addTo(map);
offlineControl.addTo(map);
```
For a more complete example, check the demo code inside the ```gh-pages``` branch.