librenms/html/js/leaflet-image.js
Tony Murray 0d246a6ffc
Custom Maps: geo map and color backgrounds (#16020)
* Custom Maps: geo map and color background
tabs blade component
geo-map blade component and related script enhancements

* Update css/js

* style fixes

* update db_schema.yaml

* fix db_schema hand edit

* ignore phpstan being wrong

* Handle null

* another possible null spot

* Use standard file cache for custom map background images

* Create map->image as jpeg so we can compress it

* whitespace fix

* Fix background cancel button when other type is selected than the saved type

* Save and restore layer

* Map must exist before creating static image

* Don't show set as image button for Google and Bing.
Bing gives an odd error, but Google won't work.
2024-05-13 08:12:59 -05:00

388 lines
13 KiB
JavaScript

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.leafletImage = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/* global L */
var queue = require('d3-queue').queue;
var cacheBusterDate = +new Date();
// leaflet-image
module.exports = function leafletImage(map, callback) {
var hasMapbox = !!L.mapbox;
var dimensions = map.getSize(),
layerQueue = new queue(1);
var canvas = document.createElement('canvas');
canvas.width = dimensions.x;
canvas.height = dimensions.y;
var ctx = canvas.getContext('2d');
// dummy canvas image when loadTile get 404 error
// and layer don't have errorTileUrl
var dummycanvas = document.createElement('canvas');
dummycanvas.width = 1;
dummycanvas.height = 1;
var dummyctx = dummycanvas.getContext('2d');
dummyctx.fillStyle = 'rgba(0,0,0,0)';
dummyctx.fillRect(0, 0, 1, 1);
// layers are drawn in the same order as they are composed in the DOM:
// tiles, paths, and then markers
map.eachLayer(drawTileLayer);
map.eachLayer(drawEsriDynamicLayer);
if (map._pathRoot) {
layerQueue.defer(handlePathRoot, map._pathRoot);
} else if (map._panes) {
var firstCanvas = map._panes.overlayPane.getElementsByTagName('canvas').item(0);
if (firstCanvas) { layerQueue.defer(handlePathRoot, firstCanvas); }
}
map.eachLayer(drawMarkerLayer);
layerQueue.awaitAll(layersDone);
function drawTileLayer(l) {
if (l instanceof L.TileLayer) layerQueue.defer(handleTileLayer, l);
else if (l._heat) layerQueue.defer(handlePathRoot, l._canvas);
}
function drawMarkerLayer(l) {
if (l instanceof L.Marker && l.options.icon instanceof L.Icon) {
layerQueue.defer(handleMarkerLayer, l);
}
}
function drawEsriDynamicLayer(l) {
if (!L.esri) return;
if (l instanceof L.esri.DynamicMapLayer) {
layerQueue.defer(handleEsriDymamicLayer, l);
}
}
function done() {
callback(null, canvas);
}
function layersDone(err, layers) {
if (err) throw err;
layers.forEach(function (layer) {
if (layer && layer.canvas) {
ctx.drawImage(layer.canvas, 0, 0);
}
});
done();
}
function handleTileLayer(layer, callback) {
// `L.TileLayer.Canvas` was removed in leaflet 1.0
var isCanvasLayer = (L.TileLayer.Canvas && layer instanceof L.TileLayer.Canvas),
canvas = document.createElement('canvas');
canvas.width = dimensions.x;
canvas.height = dimensions.y;
var ctx = canvas.getContext('2d'),
bounds = map.getPixelBounds(),
zoom = map.getZoom(),
tileSize = layer.options.tileSize;
if (zoom > layer.options.maxZoom ||
zoom < layer.options.minZoom ||
// mapbox.tileLayer
(hasMapbox &&
layer instanceof L.mapbox.tileLayer && !layer.options.tiles)) {
return callback();
}
var tileBounds = L.bounds(
bounds.min.divideBy(tileSize)._floor(),
bounds.max.divideBy(tileSize)._floor()),
tiles = [],
j, i,
tileQueue = new queue(1);
for (j = tileBounds.min.y; j <= tileBounds.max.y; j++) {
for (i = tileBounds.min.x; i <= tileBounds.max.x; i++) {
tiles.push(new L.Point(i, j));
}
}
tiles.forEach(function (tilePoint) {
var originalTilePoint = tilePoint.clone();
if (layer._adjustTilePoint) {
layer._adjustTilePoint(tilePoint);
}
var tilePos = originalTilePoint
.scaleBy(new L.Point(tileSize, tileSize))
.subtract(bounds.min);
if (tilePoint.y >= 0) {
if (isCanvasLayer) {
var tile = layer._tiles[tilePoint.x + ':' + tilePoint.y];
tileQueue.defer(canvasTile, tile, tilePos, tileSize);
} else {
var url = addCacheString(layer.getTileUrl(tilePoint));
tileQueue.defer(loadTile, url, tilePos, tileSize);
}
}
});
tileQueue.awaitAll(tileQueueFinish);
function canvasTile(tile, tilePos, tileSize, callback) {
callback(null, {
img: tile,
pos: tilePos,
size: tileSize
});
}
function loadTile(url, tilePos, tileSize, callback) {
var im = new Image();
im.crossOrigin = '';
im.onload = function () {
callback(null, {
img: this,
pos: tilePos,
size: tileSize
});
};
im.onerror = function (e) {
// use canvas instead of errorTileUrl if errorTileUrl get 404
if (layer.options.errorTileUrl != '' && e.target.errorCheck === undefined) {
e.target.errorCheck = true;
e.target.src = layer.options.errorTileUrl;
} else {
callback(null, {
img: dummycanvas,
pos: tilePos,
size: tileSize
});
}
};
im.src = url;
}
function tileQueueFinish(err, data) {
data.forEach(drawTile);
callback(null, { canvas: canvas });
}
function drawTile(d) {
ctx.drawImage(d.img, Math.floor(d.pos.x), Math.floor(d.pos.y),
d.size, d.size);
}
}
function handlePathRoot(root, callback) {
var bounds = map.getPixelBounds(),
origin = map.getPixelOrigin(),
canvas = document.createElement('canvas');
canvas.width = dimensions.x;
canvas.height = dimensions.y;
var ctx = canvas.getContext('2d');
var pos = L.DomUtil.getPosition(root).subtract(bounds.min).add(origin);
try {
ctx.drawImage(root, pos.x, pos.y, canvas.width - (pos.x * 2), canvas.height - (pos.y * 2));
callback(null, {
canvas: canvas
});
} catch(e) {
console.error('Element could not be drawn on canvas', root); // eslint-disable-line no-console
}
}
function handleMarkerLayer(marker, callback) {
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
pixelBounds = map.getPixelBounds(),
minPoint = new L.Point(pixelBounds.min.x, pixelBounds.min.y),
pixelPoint = map.project(marker.getLatLng()),
isBase64 = /^data\:/.test(marker._icon.src),
url = isBase64 ? marker._icon.src : addCacheString(marker._icon.src),
im = new Image(),
options = marker.options.icon.options,
size = options.iconSize,
pos = pixelPoint.subtract(minPoint),
anchor = L.point(options.iconAnchor || size && size.divideBy(2, true));
if (size instanceof L.Point) size = [size.x, size.y];
var x = Math.round(pos.x - size[0] + anchor.x),
y = Math.round(pos.y - anchor.y);
canvas.width = dimensions.x;
canvas.height = dimensions.y;
im.crossOrigin = '';
im.onload = function () {
ctx.drawImage(this, x, y, size[0], size[1]);
callback(null, {
canvas: canvas
});
};
im.src = url;
if (isBase64) im.onload();
}
function handleEsriDymamicLayer(dynamicLayer, callback) {
var canvas = document.createElement('canvas');
canvas.width = dimensions.x;
canvas.height = dimensions.y;
var ctx = canvas.getContext('2d');
var im = new Image();
im.crossOrigin = '';
im.src = addCacheString(dynamicLayer._currentImage._image.src);
im.onload = function() {
ctx.drawImage(im, 0, 0);
callback(null, {
canvas: canvas
});
};
}
function addCacheString(url) {
// If it's a data URL we don't want to touch this.
if (isDataURL(url) || url.indexOf('mapbox.com/styles/v1') !== -1) {
return url;
}
return url + ((url.match(/\?/)) ? '&' : '?') + 'cache=' + cacheBusterDate;
}
function isDataURL(url) {
var dataURLRegex = /^\s*data:([a-z]+\/[a-z]+(;[a-z\-]+\=[a-z\-]+)?)?(;base64)?,[a-z0-9\!\$\&\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i;
return !!url.match(dataURLRegex);
}
};
},{"d3-queue":2}],2:[function(require,module,exports){
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3_queue = global.d3_queue || {})));
}(this, function (exports) { 'use strict';
var version = "2.0.3";
var slice = [].slice;
var noabort = {};
function Queue(size) {
if (!(size >= 1)) throw new Error;
this._size = size;
this._call =
this._error = null;
this._tasks = [];
this._data = [];
this._waiting =
this._active =
this._ended =
this._start = 0; // inside a synchronous task callback?
}
Queue.prototype = queue.prototype = {
constructor: Queue,
defer: function(callback) {
if (typeof callback !== "function" || this._call) throw new Error;
if (this._error != null) return this;
var t = slice.call(arguments, 1);
t.push(callback);
++this._waiting, this._tasks.push(t);
poke(this);
return this;
},
abort: function() {
if (this._error == null) abort(this, new Error("abort"));
return this;
},
await: function(callback) {
if (typeof callback !== "function" || this._call) throw new Error;
this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
maybeNotify(this);
return this;
},
awaitAll: function(callback) {
if (typeof callback !== "function" || this._call) throw new Error;
this._call = callback;
maybeNotify(this);
return this;
}
};
function poke(q) {
if (!q._start) try { start(q); } // let the current task complete
catch (e) { if (q._tasks[q._ended + q._active - 1]) abort(q, e); } // task errored synchronously
}
function start(q) {
while (q._start = q._waiting && q._active < q._size) {
var i = q._ended + q._active,
t = q._tasks[i],
j = t.length - 1,
c = t[j];
t[j] = end(q, i);
--q._waiting, ++q._active;
t = c.apply(null, t);
if (!q._tasks[i]) continue; // task finished synchronously
q._tasks[i] = t || noabort;
}
}
function end(q, i) {
return function(e, r) {
if (!q._tasks[i]) return; // ignore multiple callbacks
--q._active, ++q._ended;
q._tasks[i] = null;
if (q._error != null) return; // ignore secondary errors
if (e != null) {
abort(q, e);
} else {
q._data[i] = r;
if (q._waiting) poke(q);
else maybeNotify(q);
}
};
}
function abort(q, e) {
var i = q._tasks.length, t;
q._error = e; // ignore active callbacks
q._data = undefined; // allow gc
q._waiting = NaN; // prevent starting
while (--i >= 0) {
if (t = q._tasks[i]) {
q._tasks[i] = null;
if (t.abort) try { t.abort(); }
catch (e) { /* ignore */ }
}
}
q._active = NaN; // allow notification
maybeNotify(q);
}
function maybeNotify(q) {
if (!q._active && q._call) q._call(q._error, q._data);
}
function queue(concurrency) {
return new Queue(arguments.length ? +concurrency : Infinity);
}
exports.version = version;
exports.queue = queue;
}));
},{}]},{},[1])(1)
});