commit 20eee8b4cf39b08c2089701ff0f7686e3dd00a79
parent ec7b6cfe2a32a1ee8639337c0ba7c6418508a171
Author: Sergej Orlov <wladimirych@gmail.com>
Date: Wed, 15 Feb 2017 21:46:00 +0300
[print] support for google, westra passes, waypoints
Diffstat:
12 files changed, 235 insertions(+), 88 deletions(-)
diff --git a/src/layers.js b/src/layers.js
@@ -237,8 +237,6 @@ export default function getLayers() {
},
]
},
-
-
{
group: 'OpenStreetMap alternatives',
layers: [
diff --git a/src/lib/leaflet.control.printPages/map-render.js b/src/lib/leaflet.control.printPages/map-render.js
@@ -114,19 +114,33 @@ class PageComposer {
}
}
-function getTempMap(zoom) {
+function getTempMap(zoom, fullSize, pixelBounds) {
const container = L.DomUtil.create('div', '', document.body);
+ let width, height, center;
+ if (fullSize) {
+ const size = pixelBounds.getSize();
+ width = size.x;
+ height = size.y;
+ center = pixelBounds.min.add(size.divideBy(2));
+ center = L.CRS.EPSG3857.pointToLatLng(center, zoom);
+ } else {
+ width = 100;
+ height = 100;
+ center = L.latLng(0, 0);
+ }
+
Object.assign(container.style, {
- width: '100px',
- height: '100px',
+ width: `${width}px`,
+ height: `${height}px`,
position: 'absolute',
left: '0',
top: '0',
- // visibility: 'hidden'
+ visibility: 'hidden'
}
);
+
const map = L.map(container, {fadeAnimation: false, zoomAnimation: false, inertia: false});
- map.setView(L.latLng(0, 0), zoom);
+ map.setView(center, zoom);
return map;
}
@@ -150,11 +164,11 @@ async function* iterateLayersTiles(layers, latLngBounds, zooms) {
} else {
zoom = zooms.satZoom;
}
- let map = getTempMap(zoom);
let pixelBounds = L.bounds(
- map.project(latLngBounds.getNorthWest()).round(),
- map.project(latLngBounds.getSouthEast()).round()
+ L.CRS.EPSG3857.latLngToPoint(latLngBounds.getNorthWest(), zoom).round(),
+ L.CRS.EPSG3857.latLngToPoint(latLngBounds.getSouthEast(), zoom).round()
);
+ let map = getTempMap(zoom, layer._rasterizeNeedsFullSizeMap, pixelBounds);
map.addLayer(layer);
let {iterateTilePromises, count} = await layer.getTilesInfo({xhrOptions: defaultXHROptions, pixelBounds});
for (let tilePromise of iterateTilePromises()) {
@@ -163,7 +177,6 @@ async function* iterateLayersTiles(layers, latLngBounds, zooms) {
doStop = yield tilePromise;
if (doStop) {
tilePromise.abortLoading();
- console.log('DO STOP3');
break;
}
}
@@ -187,7 +200,6 @@ async function* promiseQueueBuffer(source, maxActive) {
while (queue.length) {
let doStop = yield queue.shift();
if (doStop) {
- console.log('DO STOP2');
let {value, done} = await source.next(true);
if (!done) {
queue.push(value);
@@ -231,7 +243,6 @@ async function renderPages({map, pages, zooms, resolution, progressCallback}) {
try {
tileInfo = await tilePromise.tilePromise;
} catch (e) {
- console.log('DO STOP1');
queuedTilesIterator.next(true);
throw e;
}
diff --git a/src/lib/leaflet.control.track-list/track-list.js b/src/lib/leaflet.control.track-list/track-list.js
@@ -21,32 +21,6 @@ import 'lib/leaflet.control.elevation-profile';
var MeasuredEditableLine = L.MeasuredLine.extend({});
MeasuredEditableLine.include(L.Polyline.EditMixin);
-var Waypoints = L.Layer.CanvasMarkers.extend({
- options: {
- scaleDependent: true
- },
-
- clone: function() {
- var markers = this.rtree.all(),
- markersCopy;
-
- function cloneMarker(marker) {
- return {
- latlng: {lat: marker.latlng.lat, lng: marker.latlng.lng},
- label: marker.label,
- icon: marker.icon
- };
- }
-
- markersCopy = markers.map(cloneMarker);
- var options = {};
- L.extend(options, this.options, {iconScale: 1.5, labelFontSize: 14});
- return new Waypoints(markersCopy, options);
- }
- }
-);
-
-
L.Control.TrackList = L.Control.extend({
options: {position: 'bottomright'},
@@ -126,7 +100,7 @@ L.Control.TrackList = L.Control.extend({
{text: 'Delete hidden tracks', callback: this.deleteHiddenTracks.bind(this)}
]
);
- this._markerLayer = new Waypoints(null, {print: true}).addTo(map);
+ this._markerLayer = new L.Layer.CanvasMarkers(null, {print: true, scaleDependent: true}).addTo(map);
this._markerLayer.on('markerclick markercontextmenu', this.onMarkerClick, this);
map.on('resize', this._setAdaptiveHeight, this);
setTimeout(() => this._setAdaptiveHeight(), 0);
@@ -491,6 +465,7 @@ L.Control.TrackList = L.Control.extend({
var fileText = exporter(lines, name, points);
var filename = name + extension;
+ // FIXME: make function stringToBlob: convert string to byteArray first
saveAs(new Blob([fileText], {type: 'application/download'}), filename);
},
diff --git a/src/lib/leaflet.layer.google/index.js b/src/lib/leaflet.layer.google/index.js
@@ -7,7 +7,6 @@ L.Layer.Google = L.GridLayer.extend({
// Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN
initialize: function(mapType, options) {
L.GridLayer.prototype.initialize.call(this, options);
- L.Layer.prototype.constructor(options);
this.mapType = mapType;
},
@@ -55,7 +54,7 @@ L.Layer.Google = L.GridLayer.extend({
}
this._googleMap = null;
this._clearTiles();
- map.getContainer().removeChild(this._googleMapContainer);
+ L.DomUtil.remove(this._googleMapContainer);
map.off({
viewreset: this._clearTiles,
resize: this._onResize,
diff --git a/src/lib/leaflet.layer.rasterize/Bing.js b/src/lib/leaflet.layer.rasterize/Bing.js
@@ -2,7 +2,7 @@ import L from 'leaflet';
import 'lib/leaflet.layer.bing';
L.BingLayer.include({
- whenReady: function() {
+ waitTilesReadyToGrab: function() {
if (this._url) {
return Promise.resolve();
} else {
@@ -22,9 +22,5 @@ L.BingLayer.include({
cloneForPrint: function(options) {
return new L.BingLayer(this._key, L.Util.extend({}, this.options, options));
},
-
- getTilesInfo: function(printOptions) {
- return this.whenReady().then(() => L.TileLayer.prototype.getTilesInfo.call(this, printOptions));
- }
}
);
diff --git a/src/lib/leaflet.layer.rasterize/CanvasMarkers.js b/src/lib/leaflet.layer.rasterize/CanvasMarkers.js
@@ -0,0 +1,28 @@
+import L from "leaflet";
+import 'lib/leaflet.layer.canvasMarkers'
+import {CanvasLayerGrabMixin} from './TileLayer';
+
+L.Layer.CanvasMarkers.include(CanvasLayerGrabMixin);
+L.Layer.CanvasMarkers.include({
+ cloneMarkers: function() {
+ const markers = this.rtree.all();
+
+ function cloneMarker(marker) {
+ return {
+ latlng: {lat: marker.latlng.lat, lng: marker.latlng.lng},
+ label: marker.label,
+ icon: marker.icon
+ };
+ }
+
+ const markersCopy = markers.map(cloneMarker);
+ return markersCopy;
+ },
+
+ cloneForPrint: function(options) {
+ options = L.Util.extend({}, this.options, {iconScale: 1.5, labelFontSize: 14});
+ return new L.Layer.CanvasMarkers(this.cloneMarkers(), options);
+
+ }
+ }
+);
diff --git a/src/lib/leaflet.layer.rasterize/Google.js b/src/lib/leaflet.layer.rasterize/Google.js
@@ -0,0 +1,44 @@
+import L from 'leaflet';
+import 'lib/leaflet.layer.google';
+import {TileLayerGrabMixin} from './TileLayer';
+
+
+
+const GooglePrint = L.Layer.Google.extend({
+ includes: TileLayerGrabMixin,
+
+ _rasterizeNeedsFullSizeMap: true,
+
+ _dummyTile: L.DomUtil.create('div'),
+
+ onAdd: function(map) {
+ this._waitTilesReadyToGrab = new Promise((resolve) => {
+ this._tilesReadyToGrab = resolve;
+ });
+ L.Layer.Google.prototype.onAdd.call(this, map);
+ },
+
+ waitTilesReadyToGrab: function() {
+ return this._waitTilesReadyToGrab;
+ },
+
+ createTile: function() {
+ return this._dummyTile;
+ },
+
+ _fullfillPendingTiles: function() {
+ this._tilesReadyToGrab();
+ },
+
+ getTileUrl: function(coords) {
+ return this._readyTiles[this._tileCoordsToKey(coords)];
+ }
+});
+
+
+L.Layer.Google.include({
+ cloneForPrint: function(options) {
+ return new GooglePrint(this.mapType, L.Util.extend({}, this.options, options));
+ },
+});
+
diff --git a/src/lib/leaflet.layer.rasterize/TileLayer.js b/src/lib/leaflet.layer.rasterize/TileLayer.js
@@ -2,51 +2,100 @@ import L from 'leaflet';
import urlViaCorsProxy from 'lib/CORSProxy';
import {imgFromDataString} from './imgFromDataString';
-L.TileLayer.include({
+const GridLayerGrabMixin = {
+ tileImagePromiseFromCoords: function(coords) {
+ throw new Error('Method not implemented');
+ },
+
+ waitTilesReadyToGrab: function() {
+ return Promise.resolve(null);
+ },
+
+ getTilesInfo: async function(printOptions) {
+ await this.waitTilesReadyToGrab();
+ const {pixelBounds} = printOptions;
+ const tileRange = this._pxBoundsToTileRange(pixelBounds);
+ const topLeft = pixelBounds.min;
+ const tilePromiseIterator = (function*() {
+ for (let j = tileRange.min.y; j <= tileRange.max.y; j++) {
+ for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
+ let coords = new L.Point(i, j);
+ coords.z = this._tileZoom;
+ coords = this._wrapCoords(coords);
+
+ if (!this._isValidTile(coords)) {
+ continue;
+ }
+ let tilePos = this._getTilePos(coords);
+ const coordsPlusOne = coords.add(L.point(1, 1));
+ coordsPlusOne.z = coords.z;
+ const tileSize = this._getTilePos(coordsPlusOne).subtract(tilePos);
+ tilePos = tilePos.add(this._level.origin).subtract(topLeft);
+ let {tilePromise, abortLoading} = this.tileImagePromiseFromCoords(coords, printOptions);
+ yield {
+ tilePromise: tilePromise.then((image) => {
+ return {image, tilePos, tileSize};
+ }
+ ),
+ abortLoading
+ };
+ }
+ }
+ }).bind(this);
+ return {
+ iterateTilePromises: tilePromiseIterator,
+ count: (tileRange.max.x - tileRange.min.x + 1) * (tileRange.max.y - tileRange.min.y + 1)
+ };
+ }
+};
+
+const TileLayerGrabMixin = L.Util.extend({}, GridLayerGrabMixin, {
cloneForPrint: function(options) {
return L.tileLayer(this._url, L.Util.extend({}, this.options, options));
},
- getTilesInfo: function(printOptions) {
- const {pixelBounds, xhrOptions} = printOptions;
- const tileRange = this._pxBoundsToTileRange(pixelBounds);
- const topLeft = pixelBounds.min;
- const tilePromiseIterator = (function*() {
- for (let j = tileRange.min.y; j <= tileRange.max.y; j++) {
- for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
- let coords = new L.Point(i, j);
- coords.z = this._tileZoom;
-
- if (!this._isValidTile(coords)) {
- continue;
- }
-
- let url = this.getTileUrl(coords);
- if (this.options.noCors) {
- url = urlViaCorsProxy(url);
- }
- let tilePos = this._getTilePos(coords);
- const coordsPlusOne = coords.add(L.point(1, 1));
- coordsPlusOne.z = coords.z;
- const tileSize = this._getTilePos(coordsPlusOne).subtract(tilePos);
- tilePos = tilePos.add(this._level.origin).subtract(topLeft);
- let promise = this.options.xhrQueue.put(url, xhrOptions);
- yield {
- tilePromise: promise.then(imgFromDataString).then((image) => {
- return {image, tilePos, tileSize};
- }
- ),
- abortLoading: () => promise.abort()
- };
- }
- }
- }).bind(this);
- return Promise.resolve({
- iterateTilePromises: tilePromiseIterator,
- count: (tileRange.max.x - tileRange.min.x + 1) * (tileRange.max.y - tileRange.min.y + 1)
- }
- );
+ tileImagePromiseFromCoords: function(coords, printOptions) {
+ let {xhrOptions} = printOptions;
+ let url = this.getTileUrl(coords);
+ if (this.options.noCors) {
+ url = urlViaCorsProxy(url);
+ }
+ let promise = this.options.xhrQueue.put(url, xhrOptions);
+ return {
+ tilePromise: promise.then(imgFromDataString),
+ abortLoading: () => promise.abort()
+ }
}
}
);
+function noop() {
+
+}
+
+const CanvasLayerGrabMixin = L.Util.extend({}, GridLayerGrabMixin, {
+ getCanvasFromTile: function(tile) {
+ return tile;
+ },
+
+ tileImagePromiseFromCoords: function(coords) {
+ let tilePromise;
+ if (this.createTile.length < 2) {
+ let tile = this.createTile(coords);
+ tilePromise = Promise.resolve(tile);
+ } else {
+ tilePromise = new Promise((resolve) => {
+ return this.createTile(coords, resolve);
+ });
+ }
+
+ return {
+ tilePromise: tilePromise.then(this.getCanvasFromTile),
+ abortLoading: noop
+ }
+ }
+});
+
+L.TileLayer.include(TileLayerGrabMixin);
+
+export {TileLayerGrabMixin, GridLayerGrabMixin, CanvasLayerGrabMixin};
+\ No newline at end of file
diff --git a/src/lib/leaflet.layer.rasterize/WestraPasses.js b/src/lib/leaflet.layer.rasterize/WestraPasses.js
@@ -0,0 +1,41 @@
+import L from "leaflet";
+import 'lib/leaflet.layer.westraPasses';
+import {WestraPassesMarkers} from 'lib/leaflet.layer.westraPasses/westraPassesMarkers';
+import {CanvasLayerGrabMixin} from './TileLayer';
+import 'lib/leaflet.layer.canvasMarkers'
+
+const WestraPrint = L.Layer.CanvasMarkers.extend({
+ includes: CanvasLayerGrabMixin,
+
+ initialize: function(srcLayer, options) {
+ this.srcLayer = srcLayer;
+ L.Layer.CanvasMarkers.prototype.initialize.call(this, null, options);
+ },
+
+ waitTilesReadyToGrab: function() {
+ let promise;
+ if (this.srcLayer._dataLoaded) {
+ promise = Promise.resolve(null);
+ } else {
+ // FIXME: handle data load errors
+ promise = new Promise((resolve) => {
+ this.srcLayer.once('data-loaded', resolve);
+ })
+ }
+ return promise.then(() => {
+ this.addMarkers(this.srcLayer.rtree.all());
+ })
+ },
+});
+
+L.Layer.WestraPasses.addInitHook(function() {
+ this.markers.options.print = this.options.print;
+ this.options.print = false;
+});
+
+WestraPassesMarkers.include({
+ cloneForPrint: function (options) {
+ return new WestraPrint(this, L.Util.extend(
+ {}, this.options, {iconScale: 1.5, labelFontSize: 14}, options));
+ }
+});
diff --git a/src/lib/leaflet.layer.rasterize/index.js b/src/lib/leaflet.layer.rasterize/index.js
@@ -1,3 +1,6 @@
import './TileLayer'
import './Bing'
import './Yandex'
+import './Google'
+import './WestraPasses'
+import './CanvasMarkers'
diff --git a/src/lib/leaflet.layer.westraPasses/index.js b/src/lib/leaflet.layer.westraPasses/index.js
@@ -24,6 +24,7 @@ L.Layer.WestraPasses = L.Layer.extend({
}
);
},
+
_setRegionLabel: function(layerName, feature, layer) {
var latlon = layer.getBounds().getCenter();
var icon = L.divIcon({
@@ -96,4 +97,3 @@ L.Layer.WestraPasses = L.Layer.extend({
);
-
diff --git a/src/lib/leaflet.layer.westraPasses/westraPassesMarkers.js b/src/lib/leaflet.layer.westraPasses/westraPassesMarkers.js
@@ -124,6 +124,8 @@ const WestraPassesMarkers = L.Layer.CanvasMarkers.extend({
markers.push(marker);
}
this.addMarkers(markers);
+ this._dataLoaded = true;
+ this.fire('data-loaded');
},