Add marker query parameter for static maps
This commit is contained in:
parent
9e12ee6f8c
commit
275b486056
2 changed files with 90 additions and 25 deletions
BIN
public/resources/images/markerImage.png
Normal file
BIN
public/resources/images/markerImage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
|
|
@ -11,7 +11,7 @@ const zlib = require('zlib');
|
|||
// see https://github.com/lovell/sharp/issues/371
|
||||
const sharp = require('sharp');
|
||||
|
||||
const { createCanvas } = require('canvas');
|
||||
const { createCanvas, Image } = require('canvas');
|
||||
|
||||
const clone = require('clone');
|
||||
const Color = require('color');
|
||||
|
|
@ -101,35 +101,50 @@ const extractPathFromQuery = (query, transformer) => {
|
|||
const pathParts = (query.path || '').split('|');
|
||||
const path = [];
|
||||
for (const pair of pathParts) {
|
||||
const pairParts = pair.split(',');
|
||||
if (pairParts.length === 2) {
|
||||
let pair;
|
||||
if (query.latlng === '1' || query.latlng === 'true') {
|
||||
pair = [+(pairParts[1]), +(pairParts[0])];
|
||||
} else {
|
||||
pair = [+(pairParts[0]), +(pairParts[1])];
|
||||
}
|
||||
if (transformer) {
|
||||
pair = transformer(pair);
|
||||
}
|
||||
path.push(pair);
|
||||
path.push(splitCoordinatePair(pair, query, transformer));
|
||||
}
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
const renderOverlay = (z, x, y, bearing, pitch, w, h, scale,
|
||||
path, query) => {
|
||||
if (!path || path.length < 2) {
|
||||
return null;
|
||||
}
|
||||
const precisePx = (ll, zoom) => {
|
||||
const px = mercator.px(ll, 20);
|
||||
const scale = Math.pow(2, zoom - 20);
|
||||
return [px[0] * scale, px[1] * scale];
|
||||
};
|
||||
const extractMarkerFromQuery = (query, transformer) => {
|
||||
|
||||
const center = precisePx([x, y], z);
|
||||
const markerPositions = [];
|
||||
|
||||
const markerParts = (query.markers || query.marker || '').split('|');
|
||||
|
||||
if(query.marker && markerParts[0] === 'center') {return null;}
|
||||
|
||||
markerParts.forEach(marker => {
|
||||
markerPositions.push(splitCoordinatePair(marker,query,transformer));
|
||||
});
|
||||
|
||||
return markerPositions;
|
||||
};
|
||||
|
||||
const splitCoordinatePair = (pair, query, transformer) => {
|
||||
const pairParts = pair.split(',');
|
||||
if (pairParts.length === 2) {
|
||||
let coordinatePair;
|
||||
if (query.latlng === '1' || query.latlng === 'true') {
|
||||
coordinatePair = [+(pairParts[1]), +(pairParts[0])];
|
||||
} else {
|
||||
coordinatePair = [+(pairParts[0]), +(pairParts[1])];
|
||||
}
|
||||
if (transformer) {
|
||||
coordinatePair = transformer(coordinatePair);
|
||||
}
|
||||
return coordinatePair;
|
||||
}
|
||||
}
|
||||
|
||||
const precisePx = (ll, zoom) => {
|
||||
const px = mercator.px(ll, 20);
|
||||
const scale = Math.pow(2, zoom - 20);
|
||||
return [px[0] * scale, px[1] * scale];
|
||||
};
|
||||
|
||||
const georeferenceMapCenter = (x, y, z, h) => {
|
||||
let center = precisePx([x, y], z);
|
||||
|
||||
const mapHeight = 512 * (1 << z);
|
||||
const maxEdge = center[1] + h / 2;
|
||||
|
|
@ -140,6 +155,49 @@ const renderOverlay = (z, x, y, bearing, pitch, w, h, scale,
|
|||
center[1] -= minEdge;
|
||||
}
|
||||
|
||||
return center;
|
||||
};
|
||||
|
||||
const renderMarkerOverlay = (x, y, z, w, h, scale, marker) => {
|
||||
const center = georeferenceMapCenter(x, y, z, h);
|
||||
|
||||
const canvas = createCanvas(scale * w, scale * h);
|
||||
|
||||
const markers = [];
|
||||
|
||||
marker.forEach(m => {
|
||||
markers.push(precisePx(m,z));
|
||||
})
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
ctx.translate(-center[0] + w / 2, -center[1] + h / 2);
|
||||
|
||||
try {
|
||||
const imageFile = fs.readFileSync(__dirname + '/../public/resources/images/markerImage.png');
|
||||
const markerImage = new Image;
|
||||
markerImage.src = imageFile;
|
||||
|
||||
markers.forEach(marker => {
|
||||
ctx.drawImage(markerImage, marker[0] - (markerImage.width / 2) * 0.2, marker[1] - (markerImage.height) * 0.2, markerImage.width * 0.2, markerImage.height * 0.2)
|
||||
})
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
catch(e) {
|
||||
console.log('Errorloading marker image', e);
|
||||
}
|
||||
return canvas.toBuffer();
|
||||
};
|
||||
|
||||
const renderOverlay = (z, x, y, bearing, pitch, w, h, scale,
|
||||
path, query) => {
|
||||
if (!path || path.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const center = georeferenceMapCenter(x, y, z,h);
|
||||
|
||||
const canvas = createCanvas(scale * w, scale * h);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(scale, scale);
|
||||
|
|
@ -425,6 +483,13 @@ module.exports = {
|
|||
y = ll[1];
|
||||
}
|
||||
|
||||
if(req.query.marker || req.query.markers) {
|
||||
let markers = extractMarkerFromQuery(req.query, transformer);
|
||||
markers = markers === null ? [[x,y]] : markers;
|
||||
const overlay = renderMarkerOverlay(x, y, z, w, h, scale, markers);
|
||||
return respondImage(item, z, x, y, bearing, pitch, w, h, scale, format, res, next, overlay);
|
||||
}
|
||||
|
||||
const path = extractPathFromQuery(req.query, transformer);
|
||||
const overlay = renderOverlay(z, x, y, bearing, pitch, w, h, scale,
|
||||
path, req.query);
|
||||
|
|
|
|||
Loading…
Reference in a new issue