5263 lines
2.9 MiB
HTML
5263 lines
2.9 MiB
HTML
|
<!DOCTYPE html>
|
||
|
<html>
|
||
|
<head>
|
||
|
<meta charset="utf-8" />
|
||
|
<title>leaflet</title>
|
||
|
<style type="text/css">@layer htmltools {
|
||
|
.html-fill-container {
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
|
||
|
min-height: 0;
|
||
|
min-width: 0;
|
||
|
}
|
||
|
.html-fill-container > .html-fill-item {
|
||
|
|
||
|
flex: 1 1 auto;
|
||
|
min-height: 0;
|
||
|
min-width: 0;
|
||
|
}
|
||
|
.html-fill-container > :not(.html-fill-item) {
|
||
|
|
||
|
flex: 0 0 auto;
|
||
|
}
|
||
|
}
|
||
|
</style>
|
||
|
<script>(function() {
|
||
|
// If window.HTMLWidgets is already defined, then use it; otherwise create a
|
||
|
// new object. This allows preceding code to set options that affect the
|
||
|
// initialization process (though none currently exist).
|
||
|
window.HTMLWidgets = window.HTMLWidgets || {};
|
||
|
|
||
|
// See if we're running in a viewer pane. If not, we're in a web browser.
|
||
|
var viewerMode = window.HTMLWidgets.viewerMode =
|
||
|
/\bviewer_pane=1\b/.test(window.location);
|
||
|
|
||
|
// See if we're running in Shiny mode. If not, it's a static document.
|
||
|
// Note that static widgets can appear in both Shiny and static modes, but
|
||
|
// obviously, Shiny widgets can only appear in Shiny apps/documents.
|
||
|
var shinyMode = window.HTMLWidgets.shinyMode =
|
||
|
typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings;
|
||
|
|
||
|
// We can't count on jQuery being available, so we implement our own
|
||
|
// version if necessary.
|
||
|
function querySelectorAll(scope, selector) {
|
||
|
if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) {
|
||
|
return scope.find(selector);
|
||
|
}
|
||
|
if (scope.querySelectorAll) {
|
||
|
return scope.querySelectorAll(selector);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function asArray(value) {
|
||
|
if (value === null)
|
||
|
return [];
|
||
|
if ($.isArray(value))
|
||
|
return value;
|
||
|
return [value];
|
||
|
}
|
||
|
|
||
|
// Implement jQuery's extend
|
||
|
function extend(target /*, ... */) {
|
||
|
if (arguments.length == 1) {
|
||
|
return target;
|
||
|
}
|
||
|
for (var i = 1; i < arguments.length; i++) {
|
||
|
var source = arguments[i];
|
||
|
for (var prop in source) {
|
||
|
if (source.hasOwnProperty(prop)) {
|
||
|
target[prop] = source[prop];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
// IE8 doesn't support Array.forEach.
|
||
|
function forEach(values, callback, thisArg) {
|
||
|
if (values.forEach) {
|
||
|
values.forEach(callback, thisArg);
|
||
|
} else {
|
||
|
for (var i = 0; i < values.length; i++) {
|
||
|
callback.call(thisArg, values[i], i, values);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Replaces the specified method with the return value of funcSource.
|
||
|
//
|
||
|
// Note that funcSource should not BE the new method, it should be a function
|
||
|
// that RETURNS the new method. funcSource receives a single argument that is
|
||
|
// the overridden method, it can be called from the new method. The overridden
|
||
|
// method can be called like a regular function, it has the target permanently
|
||
|
// bound to it so "this" will work correctly.
|
||
|
function overrideMethod(target, methodName, funcSource) {
|
||
|
var superFunc = target[methodName] || function() {};
|
||
|
var superFuncBound = function() {
|
||
|
return superFunc.apply(target, arguments);
|
||
|
};
|
||
|
target[methodName] = funcSource(superFuncBound);
|
||
|
}
|
||
|
|
||
|
// Add a method to delegator that, when invoked, calls
|
||
|
// delegatee.methodName. If there is no such method on
|
||
|
// the delegatee, but there was one on delegator before
|
||
|
// delegateMethod was called, then the original version
|
||
|
// is invoked instead.
|
||
|
// For example:
|
||
|
//
|
||
|
// var a = {
|
||
|
// method1: function() { console.log('a1'); }
|
||
|
// method2: function() { console.log('a2'); }
|
||
|
// };
|
||
|
// var b = {
|
||
|
// method1: function() { console.log('b1'); }
|
||
|
// };
|
||
|
// delegateMethod(a, b, "method1");
|
||
|
// delegateMethod(a, b, "method2");
|
||
|
// a.method1();
|
||
|
// a.method2();
|
||
|
//
|
||
|
// The output would be "b1", "a2".
|
||
|
function delegateMethod(delegator, delegatee, methodName) {
|
||
|
var inherited = delegator[methodName];
|
||
|
delegator[methodName] = function() {
|
||
|
var target = delegatee;
|
||
|
var method = delegatee[methodName];
|
||
|
|
||
|
// The method doesn't exist on the delegatee. Instead,
|
||
|
// call the method on the delegator, if it exists.
|
||
|
if (!method) {
|
||
|
target = delegator;
|
||
|
method = inherited;
|
||
|
}
|
||
|
|
||
|
if (method) {
|
||
|
return method.apply(target, arguments);
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// Implement a vague facsimilie of jQuery's data method
|
||
|
function elementData(el, name, value) {
|
||
|
if (arguments.length == 2) {
|
||
|
return el["htmlwidget_data_" + name];
|
||
|
} else if (arguments.length == 3) {
|
||
|
el["htmlwidget_data_" + name] = value;
|
||
|
return el;
|
||
|
} else {
|
||
|
throw new Error("Wrong number of arguments for elementData: " +
|
||
|
arguments.length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
|
||
|
function escapeRegExp(str) {
|
||
|
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||
|
}
|
||
|
|
||
|
function hasClass(el, className) {
|
||
|
var re = new RegExp("\\b" + escapeRegExp(className) + "\\b");
|
||
|
return re.test(el.className);
|
||
|
}
|
||
|
|
||
|
// elements - array (or array-like object) of HTML elements
|
||
|
// className - class name to test for
|
||
|
// include - if true, only return elements with given className;
|
||
|
// if false, only return elements *without* given className
|
||
|
function filterByClass(elements, className, include) {
|
||
|
var results = [];
|
||
|
for (var i = 0; i < elements.length; i++) {
|
||
|
if (hasClass(elements[i], className) == include)
|
||
|
results.push(elements[i]);
|
||
|
}
|
||
|
return results;
|
||
|
}
|
||
|
|
||
|
function on(obj, eventName, func) {
|
||
|
if (obj.addEventListener) {
|
||
|
obj.addEventListener(eventName, func, false);
|
||
|
} else if (obj.attachEvent) {
|
||
|
obj.attachEvent(eventName, func);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function off(obj, eventName, func) {
|
||
|
if (obj.removeEventListener)
|
||
|
obj.removeEventListener(eventName, func, false);
|
||
|
else if (obj.detachEvent) {
|
||
|
obj.detachEvent(eventName, func);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Translate array of values to top/right/bottom/left, as usual with
|
||
|
// the "padding" CSS property
|
||
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||
|
function unpackPadding(value) {
|
||
|
if (typeof(value) === "number")
|
||
|
value = [value];
|
||
|
if (value.length === 1) {
|
||
|
return {top: value[0], right: value[0], bottom: value[0], left: value[0]};
|
||
|
}
|
||
|
if (value.length === 2) {
|
||
|
return {top: value[0], right: value[1], bottom: value[0], left: value[1]};
|
||
|
}
|
||
|
if (value.length === 3) {
|
||
|
return {top: value[0], right: value[1], bottom: value[2], left: value[1]};
|
||
|
}
|
||
|
if (value.length === 4) {
|
||
|
return {top: value[0], right: value[1], bottom: value[2], left: value[3]};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Convert an unpacked padding object to a CSS value
|
||
|
function paddingToCss(paddingObj) {
|
||
|
return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px";
|
||
|
}
|
||
|
|
||
|
// Makes a number suitable for CSS
|
||
|
function px(x) {
|
||
|
if (typeof(x) === "number")
|
||
|
return x + "px";
|
||
|
else
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
// Retrieves runtime widget sizing information for an element.
|
||
|
// The return value is either null, or an object with fill, padding,
|
||
|
// defaultWidth, defaultHeight fields.
|
||
|
function sizingPolicy(el) {
|
||
|
var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']");
|
||
|
if (!sizingEl)
|
||
|
return null;
|
||
|
var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}");
|
||
|
if (viewerMode) {
|
||
|
return sp.viewer;
|
||
|
} else {
|
||
|
return sp.browser;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// @param tasks Array of strings (or falsy value, in which case no-op).
|
||
|
// Each element must be a valid JavaScript expression that yields a
|
||
|
// function. Or, can be an array of objects with "code" and "data"
|
||
|
// properties; in this case, the "code" property should be a string
|
||
|
// of JS that's an expr that yields a function, and "data" should be
|
||
|
// an object that will be added as an additional argument when that
|
||
|
// function is called.
|
||
|
// @param target The object that will be "this" for each function
|
||
|
// execution.
|
||
|
// @param args Array of arguments to be passed to the functions. (The
|
||
|
// same arguments will be passed to all functions.)
|
||
|
function evalAndRun(tasks, target, args) {
|
||
|
if (tasks) {
|
||
|
forEach(tasks, function(task) {
|
||
|
var theseArgs = args;
|
||
|
if (typeof(task) === "object") {
|
||
|
theseArgs = theseArgs.concat([task.data]);
|
||
|
task = task.code;
|
||
|
}
|
||
|
var taskFunc = tryEval(task);
|
||
|
if (typeof(taskFunc) !== "function") {
|
||
|
throw new Error("Task must be a function! Source:\n" + task);
|
||
|
}
|
||
|
taskFunc.apply(target, theseArgs);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Attempt eval() both with and without enclosing in parentheses.
|
||
|
// Note that enclosing coerces a function declaration into
|
||
|
// an expression that eval() can parse
|
||
|
// (otherwise, a SyntaxError is thrown)
|
||
|
function tryEval(code) {
|
||
|
var result = null;
|
||
|
try {
|
||
|
result = eval("(" + code + ")");
|
||
|
} catch(error) {
|
||
|
if (!(error instanceof SyntaxError)) {
|
||
|
throw error;
|
||
|
}
|
||
|
try {
|
||
|
result = eval(code);
|
||
|
} catch(e) {
|
||
|
if (e instanceof SyntaxError) {
|
||
|
throw error;
|
||
|
} else {
|
||
|
throw e;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function initSizing(el) {
|
||
|
var sizing = sizingPolicy(el);
|
||
|
if (!sizing)
|
||
|
return;
|
||
|
|
||
|
var cel = document.getElementById("htmlwidget_container");
|
||
|
if (!cel)
|
||
|
return;
|
||
|
|
||
|
if (typeof(sizing.padding) !== "undefined") {
|
||
|
document.body.style.margin = "0";
|
||
|
document.body.style.padding = paddingToCss(unpackPadding(sizing.padding));
|
||
|
}
|
||
|
|
||
|
if (sizing.fill) {
|
||
|
document.body.style.overflow = "hidden";
|
||
|
document.body.style.width = "100%";
|
||
|
document.body.style.height = "100%";
|
||
|
document.documentElement.style.width = "100%";
|
||
|
document.documentElement.style.height = "100%";
|
||
|
cel.style.position = "absolute";
|
||
|
var pad = unpackPadding(sizing.padding);
|
||
|
cel.style.top = pad.top + "px";
|
||
|
cel.style.right = pad.right + "px";
|
||
|
cel.style.bottom = pad.bottom + "px";
|
||
|
cel.style.left = pad.left + "px";
|
||
|
el.style.width = "100%";
|
||
|
el.style.height = "100%";
|
||
|
|
||
|
return {
|
||
|
getWidth: function() { return cel.getBoundingClientRect().width; },
|
||
|
getHeight: function() { return cel.getBoundingClientRect().height; }
|
||
|
};
|
||
|
|
||
|
} else {
|
||
|
el.style.width = px(sizing.width);
|
||
|
el.style.height = px(sizing.height);
|
||
|
|
||
|
return {
|
||
|
getWidth: function() { return cel.getBoundingClientRect().width; },
|
||
|
getHeight: function() { return cel.getBoundingClientRect().height; }
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Default implementations for methods
|
||
|
var defaults = {
|
||
|
find: function(scope) {
|
||
|
return querySelectorAll(scope, "." + this.name);
|
||
|
},
|
||
|
renderError: function(el, err) {
|
||
|
var $el = $(el);
|
||
|
|
||
|
this.clearError(el);
|
||
|
|
||
|
// Add all these error classes, as Shiny does
|
||
|
var errClass = "shiny-output-error";
|
||
|
if (err.type !== null) {
|
||
|
// use the classes of the error condition as CSS class names
|
||
|
errClass = errClass + " " + $.map(asArray(err.type), function(type) {
|
||
|
return errClass + "-" + type;
|
||
|
}).join(" ");
|
||
|
}
|
||
|
errClass = errClass + " htmlwidgets-error";
|
||
|
|
||
|
// Is el inline or block? If inline or inline-block, just display:none it
|
||
|
// and add an inline error.
|
||
|
var display = $el.css("display");
|
||
|
$el.data("restore-display-mode", display);
|
||
|
|
||
|
if (display === "inline" || display === "inline-block") {
|
||
|
$el.hide();
|
||
|
if (err.message !== "") {
|
||
|
var errorSpan = $("<span>").addClass(errClass);
|
||
|
errorSpan.text(err.message);
|
||
|
$el.after(errorSpan);
|
||
|
}
|
||
|
} else if (display === "block") {
|
||
|
// If block, add an error just after the el, set visibility:none on the
|
||
|
// el, and position the error to be on top of the el.
|
||
|
// Mark it with a unique ID and CSS class so we can remove it later.
|
||
|
$el.css("visibility", "hidden");
|
||
|
if (err.message !== "") {
|
||
|
var errorDiv = $("<div>").addClass(errClass).css("position", "absolute")
|
||
|
.css("top", el.offsetTop)
|
||
|
.css("left", el.offsetLeft)
|
||
|
// setting width can push out the page size, forcing otherwise
|
||
|
// unnecessary scrollbars to appear and making it impossible for
|
||
|
// the element to shrink; so use max-width instead
|
||
|
.css("maxWidth", el.offsetWidth)
|
||
|
.css("height", el.offsetHeight);
|
||
|
errorDiv.text(err.message);
|
||
|
$el.after(errorDiv);
|
||
|
|
||
|
// Really dumb way to keep the size/position of the error in sync with
|
||
|
// the parent element as the window is resized or whatever.
|
||
|
var intId = setInterval(function() {
|
||
|
if (!errorDiv[0].parentElement) {
|
||
|
clearInterval(intId);
|
||
|
return;
|
||
|
}
|
||
|
errorDiv
|
||
|
.css("top", el.offsetTop)
|
||
|
.css("left", el.offsetLeft)
|
||
|
.css("maxWidth", el.offsetWidth)
|
||
|
.css("height", el.offsetHeight);
|
||
|
}, 500);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
clearError: function(el) {
|
||
|
var $el = $(el);
|
||
|
var display = $el.data("restore-display-mode");
|
||
|
$el.data("restore-display-mode", null);
|
||
|
|
||
|
if (display === "inline" || display === "inline-block") {
|
||
|
if (display)
|
||
|
$el.css("display", display);
|
||
|
$(el.nextSibling).filter(".htmlwidgets-error").remove();
|
||
|
} else if (display === "block"){
|
||
|
$el.css("visibility", "inherit");
|
||
|
$(el.nextSibling).filter(".htmlwidgets-error").remove();
|
||
|
}
|
||
|
},
|
||
|
sizing: {}
|
||
|
};
|
||
|
|
||
|
// Called by widget bindings to register a new type of widget. The definition
|
||
|
// object can contain the following properties:
|
||
|
// - name (required) - A string indicating the binding name, which will be
|
||
|
// used by default as the CSS classname to look for.
|
||
|
// - initialize (optional) - A function(el) that will be called once per
|
||
|
// widget element; if a value is returned, it will be passed as the third
|
||
|
// value to renderValue.
|
||
|
// - renderValue (required) - A function(el, data, initValue) that will be
|
||
|
// called with data. Static contexts will cause this to be called once per
|
||
|
// element; Shiny apps will cause this to be called multiple times per
|
||
|
// element, as the data changes.
|
||
|
window.HTMLWidgets.widget = function(definition) {
|
||
|
if (!definition.name) {
|
||
|
throw new Error("Widget must have a name");
|
||
|
}
|
||
|
if (!definition.type) {
|
||
|
throw new Error("Widget must have a type");
|
||
|
}
|
||
|
// Currently we only support output widgets
|
||
|
if (definition.type !== "output") {
|
||
|
throw new Error("Unrecognized widget type '" + definition.type + "'");
|
||
|
}
|
||
|
// TODO: Verify that .name is a valid CSS classname
|
||
|
|
||
|
// Support new-style instance-bound definitions. Old-style class-bound
|
||
|
// definitions have one widget "object" per widget per type/class of
|
||
|
// widget; the renderValue and resize methods on such widget objects
|
||
|
// take el and instance arguments, because the widget object can't
|
||
|
// store them. New-style instance-bound definitions have one widget
|
||
|
// object per widget instance; the definition that's passed in doesn't
|
||
|
// provide renderValue or resize methods at all, just the single method
|
||
|
// factory(el, width, height)
|
||
|
// which returns an object that has renderValue(x) and resize(w, h).
|
||
|
// This enables a far more natural programming style for the widget
|
||
|
// author, who can store per-instance state using either OO-style
|
||
|
// instance fields or functional-style closure variables (I guess this
|
||
|
// is in contrast to what can only be called C-style pseudo-OO which is
|
||
|
// what we required before).
|
||
|
if (definition.factory) {
|
||
|
definition = createLegacyDefinitionAdapter(definition);
|
||
|
}
|
||
|
|
||
|
if (!definition.renderValue) {
|
||
|
throw new Error("Widget must have a renderValue function");
|
||
|
}
|
||
|
|
||
|
// For static rendering (non-Shiny), use a simple widget registration
|
||
|
// scheme. We also use this scheme for Shiny apps/documents that also
|
||
|
// contain static widgets.
|
||
|
window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || [];
|
||
|
// Merge defaults into the definition; don't mutate the original definition.
|
||
|
var staticBinding = extend({}, defaults, definition);
|
||
|
overrideMethod(staticBinding, "find", function(superfunc) {
|
||
|
return function(scope) {
|
||
|
var results = superfunc(scope);
|
||
|
// Filter out Shiny outputs, we only want the static kind
|
||
|
return filterByClass(results, "html-widget-output", false);
|
||
|
};
|
||
|
});
|
||
|
window.HTMLWidgets.widgets.push(staticBinding);
|
||
|
|
||
|
if (shinyMode) {
|
||
|
// Shiny is running. Register the definition with an output binding.
|
||
|
// The definition itself will not be the output binding, instead
|
||
|
// we will make an output binding object that delegates to the
|
||
|
// definition. This is because we foolishly used the same method
|
||
|
// name (renderValue) for htmlwidgets definition and Shiny bindings
|
||
|
// but they actually have quite different semantics (the Shiny
|
||
|
// bindings receive data that includes lots of metadata that it
|
||
|
// strips off before calling htmlwidgets renderValue). We can't
|
||
|
// just ignore the difference because in some widgets it's helpful
|
||
|
// to call this.renderValue() from inside of resize(), and if
|
||
|
// we're not delegating, then that call will go to the Shiny
|
||
|
// version instead of the htmlwidgets version.
|
||
|
|
||
|
// Merge defaults with definition, without mutating either.
|
||
|
var bindingDef = extend({}, defaults, definition);
|
||
|
|
||
|
// This object will be our actual Shiny binding.
|
||
|
var shinyBinding = new Shiny.OutputBinding();
|
||
|
|
||
|
// With a few exceptions, we'll want to simply use the bindingDef's
|
||
|
// version of methods if they are available, otherwise fall back to
|
||
|
// Shiny's defaults. NOTE: If Shiny's output bindings gain additional
|
||
|
// methods in the future, and we want them to be overrideable by
|
||
|
// HTMLWidget binding definitions, then we'll need to add them to this
|
||
|
// list.
|
||
|
delegateMethod(shinyBinding, bindingDef, "getId");
|
||
|
delegateMethod(shinyBinding, bindingDef, "onValueChange");
|
||
|
delegateMethod(shinyBinding, bindingDef, "onValueError");
|
||
|
delegateMethod(shinyBinding, bindingDef, "renderError");
|
||
|
delegateMethod(shinyBinding, bindingDef, "clearError");
|
||
|
delegateMethod(shinyBinding, bindingDef, "showProgress");
|
||
|
|
||
|
// The find, renderValue, and resize are handled differently, because we
|
||
|
// want to actually decorate the behavior of the bindingDef methods.
|
||
|
|
||
|
shinyBinding.find = function(scope) {
|
||
|
var results = bindingDef.find(scope);
|
||
|
|
||
|
// Only return elements that are Shiny outputs, not static ones
|
||
|
var dynamicResults = results.filter(".html-widget-output");
|
||
|
|
||
|
// It's possible that whatever caused Shiny to think there might be
|
||
|
// new dynamic outputs, also caused there to be new static outputs.
|
||
|
// Since there might be lots of different htmlwidgets bindings, we
|
||
|
// schedule execution for later--no need to staticRender multiple
|
||
|
// times.
|
||
|
if (results.length !== dynamicResults.length)
|
||
|
scheduleStaticRender();
|
||
|
|
||
|
return dynamicResults;
|
||
|
};
|
||
|
|
||
|
// Wrap renderValue to handle initialization, which unfortunately isn't
|
||
|
// supported natively by Shiny at the time of this writing.
|
||
|
|
||
|
shinyBinding.renderValue = function(el, data) {
|
||
|
Shiny.renderDependencies(data.deps);
|
||
|
// Resolve strings marked as javascript literals to objects
|
||
|
if (!(data.evals instanceof Array)) data.evals = [data.evals];
|
||
|
for (var i = 0; data.evals && i < data.evals.length; i++) {
|
||
|
window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]);
|
||
|
}
|
||
|
if (!bindingDef.renderOnNullValue) {
|
||
|
if (data.x === null) {
|
||
|
el.style.visibility = "hidden";
|
||
|
return;
|
||
|
} else {
|
||
|
el.style.visibility = "inherit";
|
||
|
}
|
||
|
}
|
||
|
if (!elementData(el, "initialized")) {
|
||
|
initSizing(el);
|
||
|
|
||
|
elementData(el, "initialized", true);
|
||
|
if (bindingDef.initialize) {
|
||
|
var rect = el.getBoundingClientRect();
|
||
|
var result = bindingDef.initialize(el, rect.width, rect.height);
|
||
|
elementData(el, "init_result", result);
|
||
|
}
|
||
|
}
|
||
|
bindingDef.renderValue(el, data.x, elementData(el, "init_result"));
|
||
|
evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]);
|
||
|
};
|
||
|
|
||
|
// Only override resize if bindingDef implements it
|
||
|
if (bindingDef.resize) {
|
||
|
shinyBinding.resize = function(el, width, height) {
|
||
|
// Shiny can call resize before initialize/renderValue have been
|
||
|
// called, which doesn't make sense for widgets.
|
||
|
if (elementData(el, "initialized")) {
|
||
|
bindingDef.resize(el, width, height, elementData(el, "init_result"));
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
Shiny.outputBindings.register(shinyBinding, bindingDef.name);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var scheduleStaticRenderTimerId = null;
|
||
|
function scheduleStaticRender() {
|
||
|
if (!scheduleStaticRenderTimerId) {
|
||
|
scheduleStaticRenderTimerId = setTimeout(function() {
|
||
|
scheduleStaticRenderTimerId = null;
|
||
|
window.HTMLWidgets.staticRender();
|
||
|
}, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Render static widgets after the document finishes loading
|
||
|
// Statically render all elements that are of this widget's class
|
||
|
window.HTMLWidgets.staticRender = function() {
|
||
|
var bindings = window.HTMLWidgets.widgets || [];
|
||
|
forEach(bindings, function(binding) {
|
||
|
var matches = binding.find(document.documentElement);
|
||
|
forEach(matches, function(el) {
|
||
|
var sizeObj = initSizing(el, binding);
|
||
|
|
||
|
var getSize = function(el) {
|
||
|
if (sizeObj) {
|
||
|
return {w: sizeObj.getWidth(), h: sizeObj.getHeight()}
|
||
|
} else {
|
||
|
var rect = el.getBoundingClientRect();
|
||
|
return {w: rect.width, h: rect.height}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (hasClass(el, "html-widget-static-bound"))
|
||
|
return;
|
||
|
el.className = el.className + " html-widget-static-bound";
|
||
|
|
||
|
var initResult;
|
||
|
if (binding.initialize) {
|
||
|
var size = getSize(el);
|
||
|
initResult = binding.initialize(el, size.w, size.h);
|
||
|
elementData(el, "init_result", initResult);
|
||
|
}
|
||
|
|
||
|
if (binding.resize) {
|
||
|
var lastSize = getSize(el);
|
||
|
var resizeHandler = function(e) {
|
||
|
var size = getSize(el);
|
||
|
if (size.w === 0 && size.h === 0)
|
||
|
return;
|
||
|
if (size.w === lastSize.w && size.h === lastSize.h)
|
||
|
return;
|
||
|
lastSize = size;
|
||
|
binding.resize(el, size.w, size.h, initResult);
|
||
|
};
|
||
|
|
||
|
on(window, "resize", resizeHandler);
|
||
|
|
||
|
// This is needed for cases where we're running in a Shiny
|
||
|
// app, but the widget itself is not a Shiny output, but
|
||
|
// rather a simple static widget. One example of this is
|
||
|
// an rmarkdown document that has runtime:shiny and widget
|
||
|
// that isn't in a render function. Shiny only knows to
|
||
|
// call resize handlers for Shiny outputs, not for static
|
||
|
// widgets, so we do it ourselves.
|
||
|
if (window.jQuery) {
|
||
|
window.jQuery(document).on(
|
||
|
"shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets",
|
||
|
resizeHandler
|
||
|
);
|
||
|
window.jQuery(document).on(
|
||
|
"hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets",
|
||
|
resizeHandler
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// This is needed for the specific case of ioslides, which
|
||
|
// flips slides between display:none and display:block.
|
||
|
// Ideally we would not have to have ioslide-specific code
|
||
|
// here, but rather have ioslides raise a generic event,
|
||
|
// but the rmarkdown package just went to CRAN so the
|
||
|
// window to getting that fixed may be long.
|
||
|
if (window.addEventListener) {
|
||
|
// It's OK to limit this to window.addEventListener
|
||
|
// browsers because ioslides itself only supports
|
||
|
// such browsers.
|
||
|
on(document, "slideenter", resizeHandler);
|
||
|
on(document, "slideleave", resizeHandler);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']");
|
||
|
if (scriptData) {
|
||
|
var data = JSON.parse(scriptData.textContent || scriptData.text);
|
||
|
// Resolve strings marked as javascript literals to objects
|
||
|
if (!(data.evals instanceof Array)) data.evals = [data.evals];
|
||
|
for (var k = 0; data.evals && k < data.evals.length; k++) {
|
||
|
window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]);
|
||
|
}
|
||
|
binding.renderValue(el, data.x, initResult);
|
||
|
evalAndRun(data.jsHooks.render, initResult, [el, data.x]);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
invokePostRenderHandlers();
|
||
|
}
|
||
|
|
||
|
|
||
|
function has_jQuery3() {
|
||
|
if (!window.jQuery) {
|
||
|
return false;
|
||
|
}
|
||
|
var $version = window.jQuery.fn.jquery;
|
||
|
var $major_version = parseInt($version.split(".")[0]);
|
||
|
return $major_version >= 3;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
/ Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's
|
||
|
/ on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now
|
||
|
/ really means $(setTimeout(fn)).
|
||
|
/ https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous
|
||
|
/
|
||
|
/ Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny
|
||
|
/ one tick later than it did before, which means staticRender() is
|
||
|
/ called renderValue() earlier than (advanced) widget authors might be expecting.
|
||
|
/ https://github.com/rstudio/shiny/issues/2630
|
||
|
/
|
||
|
/ For a concrete example, leaflet has some methods (e.g., updateBounds)
|
||
|
/ which reference Shiny methods registered in initShiny (e.g., setInputValue).
|
||
|
/ Since leaflet is privy to this life-cycle, it knows to use setTimeout() to
|
||
|
/ delay execution of those methods (until Shiny methods are ready)
|
||
|
/ https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268
|
||
|
/
|
||
|
/ Ideally widget authors wouldn't need to use this setTimeout() hack that
|
||
|
/ leaflet uses to call Shiny methods on a staticRender(). In the long run,
|
||
|
/ the logic initShiny should be broken up so that method registration happens
|
||
|
/ right away, but binding happens later.
|
||
|
*/
|
||
|
function maybeStaticRenderLater() {
|
||
|
if (shinyMode && has_jQuery3()) {
|
||
|
window.jQuery(window.HTMLWidgets.staticRender);
|
||
|
} else {
|
||
|
window.HTMLWidgets.staticRender();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (document.addEventListener) {
|
||
|
document.addEventListener("DOMContentLoaded", function() {
|
||
|
document.removeEventListener("DOMContentLoaded", arguments.callee, false);
|
||
|
maybeStaticRenderLater();
|
||
|
}, false);
|
||
|
} else if (document.attachEvent) {
|
||
|
document.attachEvent("onreadystatechange", function() {
|
||
|
if (document.readyState === "complete") {
|
||
|
document.detachEvent("onreadystatechange", arguments.callee);
|
||
|
maybeStaticRenderLater();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
|
||
|
window.HTMLWidgets.getAttachmentUrl = function(depname, key) {
|
||
|
// If no key, default to the first item
|
||
|
if (typeof(key) === "undefined")
|
||
|
key = 1;
|
||
|
|
||
|
var link = document.getElementById(depname + "-" + key + "-attachment");
|
||
|
if (!link) {
|
||
|
throw new Error("Attachment " + depname + "/" + key + " not found in document");
|
||
|
}
|
||
|
return link.getAttribute("href");
|
||
|
};
|
||
|
|
||
|
window.HTMLWidgets.dataframeToD3 = function(df) {
|
||
|
var names = [];
|
||
|
var length;
|
||
|
for (var name in df) {
|
||
|
if (df.hasOwnProperty(name))
|
||
|
names.push(name);
|
||
|
if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") {
|
||
|
throw new Error("All fields must be arrays");
|
||
|
} else if (typeof(length) !== "undefined" && length !== df[name].length) {
|
||
|
throw new Error("All fields must be arrays of the same length");
|
||
|
}
|
||
|
length = df[name].length;
|
||
|
}
|
||
|
var results = [];
|
||
|
var item;
|
||
|
for (var row = 0; row < length; row++) {
|
||
|
item = {};
|
||
|
for (var col = 0; col < names.length; col++) {
|
||
|
item[names[col]] = df[names[col]][row];
|
||
|
}
|
||
|
results.push(item);
|
||
|
}
|
||
|
return results;
|
||
|
};
|
||
|
|
||
|
window.HTMLWidgets.transposeArray2D = function(array) {
|
||
|
if (array.length === 0) return array;
|
||
|
var newArray = array[0].map(function(col, i) {
|
||
|
return array.map(function(row) {
|
||
|
return row[i]
|
||
|
})
|
||
|
});
|
||
|
return newArray;
|
||
|
};
|
||
|
// Split value at splitChar, but allow splitChar to be escaped
|
||
|
// using escapeChar. Any other characters escaped by escapeChar
|
||
|
// will be included as usual (including escapeChar itself).
|
||
|
function splitWithEscape(value, splitChar, escapeChar) {
|
||
|
var results = [];
|
||
|
var escapeMode = false;
|
||
|
var currentResult = "";
|
||
|
for (var pos = 0; pos < value.length; pos++) {
|
||
|
if (!escapeMode) {
|
||
|
if (value[pos] === splitChar) {
|
||
|
results.push(currentResult);
|
||
|
currentResult = "";
|
||
|
} else if (value[pos] === escapeChar) {
|
||
|
escapeMode = true;
|
||
|
} else {
|
||
|
currentResult += value[pos];
|
||
|
}
|
||
|
} else {
|
||
|
currentResult += value[pos];
|
||
|
escapeMode = false;
|
||
|
}
|
||
|
}
|
||
|
if (currentResult !== "") {
|
||
|
results.push(currentResult);
|
||
|
}
|
||
|
return results;
|
||
|
}
|
||
|
// Function authored by Yihui/JJ Allaire
|
||
|
window.HTMLWidgets.evaluateStringMember = function(o, member) {
|
||
|
var parts = splitWithEscape(member, '.', '\\');
|
||
|
for (var i = 0, l = parts.length; i < l; i++) {
|
||
|
var part = parts[i];
|
||
|
// part may be a character or 'numeric' member name
|
||
|
if (o !== null && typeof o === "object" && part in o) {
|
||
|
if (i == (l - 1)) { // if we are at the end of the line then evalulate
|
||
|
if (typeof o[part] === "string")
|
||
|
o[part] = tryEval(o[part]);
|
||
|
} else { // otherwise continue to next embedded object
|
||
|
o = o[part];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Retrieve the HTMLWidget instance (i.e. the return value of an
|
||
|
// HTMLWidget binding's initialize() or factory() function)
|
||
|
// associated with an element, or null if none.
|
||
|
window.HTMLWidgets.getInstance = function(el) {
|
||
|
return elementData(el, "init_result");
|
||
|
};
|
||
|
|
||
|
// Finds the first element in the scope that matches the selector,
|
||
|
// and returns the HTMLWidget instance (i.e. the return value of
|
||
|
// an HTMLWidget binding's initialize() or factory() function)
|
||
|
// associated with that element, if any. If no element matches the
|
||
|
// selector, or the first matching element has no HTMLWidget
|
||
|
// instance associated with it, then null is returned.
|
||
|
//
|
||
|
// The scope argument is optional, and defaults to window.document.
|
||
|
window.HTMLWidgets.find = function(scope, selector) {
|
||
|
if (arguments.length == 1) {
|
||
|
selector = scope;
|
||
|
scope = document;
|
||
|
}
|
||
|
|
||
|
var el = scope.querySelector(selector);
|
||
|
if (el === null) {
|
||
|
return null;
|
||
|
} else {
|
||
|
return window.HTMLWidgets.getInstance(el);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Finds all elements in the scope that match the selector, and
|
||
|
// returns the HTMLWidget instances (i.e. the return values of
|
||
|
// an HTMLWidget binding's initialize() or factory() function)
|
||
|
// associated with the elements, in an array. If elements that
|
||
|
// match the selector don't have an associated HTMLWidget
|
||
|
// instance, the returned array will contain nulls.
|
||
|
//
|
||
|
// The scope argument is optional, and defaults to window.document.
|
||
|
window.HTMLWidgets.findAll = function(scope, selector) {
|
||
|
if (arguments.length == 1) {
|
||
|
selector = scope;
|
||
|
scope = document;
|
||
|
}
|
||
|
|
||
|
var nodes = scope.querySelectorAll(selector);
|
||
|
var results = [];
|
||
|
for (var i = 0; i < nodes.length; i++) {
|
||
|
results.push(window.HTMLWidgets.getInstance(nodes[i]));
|
||
|
}
|
||
|
return results;
|
||
|
};
|
||
|
|
||
|
var postRenderHandlers = [];
|
||
|
function invokePostRenderHandlers() {
|
||
|
while (postRenderHandlers.length) {
|
||
|
var handler = postRenderHandlers.shift();
|
||
|
if (handler) {
|
||
|
handler();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Register the given callback function to be invoked after the
|
||
|
// next time static widgets are rendered.
|
||
|
window.HTMLWidgets.addPostRenderHandler = function(callback) {
|
||
|
postRenderHandlers.push(callback);
|
||
|
};
|
||
|
|
||
|
// Takes a new-style instance-bound definition, and returns an
|
||
|
// old-style class-bound definition. This saves us from having
|
||
|
// to rewrite all the logic in this file to accomodate both
|
||
|
// types of definitions.
|
||
|
function createLegacyDefinitionAdapter(defn) {
|
||
|
var result = {
|
||
|
name: defn.name,
|
||
|
type: defn.type,
|
||
|
initialize: function(el, width, height) {
|
||
|
return defn.factory(el, width, height);
|
||
|
},
|
||
|
renderValue: function(el, x, instance) {
|
||
|
return instance.renderValue(x);
|
||
|
},
|
||
|
resize: function(el, width, height, instance) {
|
||
|
return instance.resize(width, height);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (defn.find)
|
||
|
result.find = defn.find;
|
||
|
if (defn.renderError)
|
||
|
result.renderError = defn.renderError;
|
||
|
if (defn.clearError)
|
||
|
result.clearError = defn.clearError;
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
})();
|
||
|
</script>
|
||
|
<script>/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
||
|
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e
|
||
|
</script>
|
||
|
<style type="text/css">.leaflet-pane,.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile-container,.leaflet-pane > svg,.leaflet-pane > canvas,.leaflet-zoom-box,.leaflet-image-layer,.leaflet-layer {position: absolute;left: 0;top: 0;}.leaflet-container {overflow: hidden;}.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow {-webkit-user-select: none;-moz-user-select: none;user-select: none;-webkit-user-drag: none;}.leaflet-safari .leaflet-tile {image-rendering: -webkit-optimize-contrast;}.leaflet-safari .leaflet-tile-container {width: 1600px;height: 1600px;-webkit-transform-origin: 0 0;}.leaflet-marker-icon,.leaflet-marker-shadow {display: block;}.leaflet-container .leaflet-overlay-pane svg,.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-shadow-pane img,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer {max-width: none !important;max-height: none !important;}.leaflet-container.leaflet-touch-zoom {-ms-touch-action: pan-x pan-y;touch-action: pan-x pan-y;}.leaflet-container.leaflet-touch-drag {-ms-touch-action: pinch-zoom;touch-action: none;touch-action: pinch-zoom;}.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {-ms-touch-action: none;touch-action: none;}.leaflet-container {-webkit-tap-highlight-color: transparent;}.leaflet-container a {-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);}.leaflet-tile {filter: inherit;visibility: hidden;}.leaflet-tile-loaded {visibility: inherit;}.leaflet-zoom-box {width: 0;height: 0;-moz-box-sizing: border-box;box-sizing: border-box;z-index: 800;}.leaflet-overlay-pane svg {-moz-user-select: none;}.leaflet-pane { z-index: 400; }.leaflet-tile-pane { z-index: 200; }.leaflet-overlay-pane { z-index: 400; }.leaflet-shadow-pane { z-index: 500; }.leaflet-marker-pane { z-index: 600; }.leaflet-tooltip-pane { z-index: 650; }.leaflet-popup-pane { z-index: 700; }.leaflet-map-pane canvas { z-index: 100; }.leaflet-map-pane svg { z-index: 200; }.leaflet-vml-shape {width: 1px;height: 1px;}.lvml {behavior: url(#default#VML);display: inline-block;position: absolute;}.leaflet-control {position: relative;z-index: 800;pointer-events: visiblePainted; pointer-events: auto;}.leaflet-top,.leaflet-bottom {position: absolute;z-index: 1000;pointer-events: none;}.leaflet-top {top: 0;}.leaflet-right {right: 0;}.leaflet-bottom {bottom: 0;}.leaflet-left {left: 0;}.leaflet-control {float: left;clear: both;}.leaflet-right .leaflet-control {float: right;}.leaflet-top .leaflet-control {margin-top: 10px;}.leaflet-bottom .leaflet-control {margin-bottom: 10px;}.leaflet-left .leaflet-control {margin-left: 10px;}.leaflet-right .leaflet-control {margin-right: 10px;}.leaflet-fade-anim .leaflet-tile {will-change: opacity;}.leaflet-fade-anim .leaflet-popup {opacity: 0;-webkit-transition: opacity 0.2s linear;-moz-transition: opacity 0.2s linear;-o-transition: opacity 0.2s linear;transition: opacity 0.2s linear;}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {opacity: 1;}.leaflet-zoom-animated {-webkit-transform-origin: 0 0;-ms-transform-origin: 0 0;transform-origin: 0 0;}.leaflet-zoom-anim .leaflet-zoom-animated {will-change: transform;}.leaflet-zoom-anim .leaflet-zoom-animated {-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);transition: transform 0.25s cubic-bezier(0,0,0.25,1);}.leaflet-zoom-anim .leaflet-tile,.leaflet-pan-anim .leaflet-tile {-webkit-transition: none;-moz-transition: none;-o-transition: none;transition: none;}.leaflet-zoom-anim .leaflet-zoom-hide {visibility: hidden;}.leaflet-interactive {cursor: pointer;}.leaflet-grab {cursor: -webkit-grab;cursor: -moz-grab;}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive {cursor: crosshair;}.leaflet-popup-pane,.leaflet-control {cursor: auto;}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable {cursor: move;cursor: -webkit-grabbing;cursor: -moz-grabbing;}.le
|
||
|
<script>/* @preserve
|
||
|
* Leaflet 1.3.1+Detached: ba6f97fff8647e724e4dfe66d2ed7da11f908989.ba6f97f, a JS library for interactive maps. https://leafletjs.com
|
||
|
* (c) 2010-2017 Vladimir Agafonkin, (c) 2010-2011 CloudMade
|
||
|
*/
|
||
|
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i(t.L={})}(this,function(t){"use strict";function i(t){var i,e,n,o;for(e=1,n=arguments.length;e<n;e++){o=arguments[e];for(i in o)t[i]=o[i]}return t}function e(t,i){var e=Array.prototype.slice;if(t.bind)return t.bind.apply(t,e.call(arguments,1));var n=e.call(arguments,2);return function(){return t.apply(i,n.length?n.concat(e.call(arguments)):arguments)}}function n(t){return t._leaflet_id=t._leaflet_id||++ti,t._leaflet_id}function o(t,i,e){var n,o,s,r;return r=function(){n=!1,o&&(s.apply(e,o),o=!1)},s=function(){n?o=arguments:(t.apply(e,arguments),setTimeout(r,i),n=!0)}}function s(t,i,e){var n=i[1],o=i[0],s=n-o;return t===n&&e?t:((t-o)%s+s)%s+o}function r(){return!1}function a(t,i){var e=Math.pow(10,void 0===i?6:i);return Math.round(t*e)/e}function h(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function u(t){return h(t).split(/\s+/)}function l(t,i){t.hasOwnProperty("options")||(t.options=t.options?Qt(t.options):{});for(var e in i)t.options[e]=i[e];return t.options}function c(t,i,e){var n=[];for(var o in t)n.push(encodeURIComponent(e?o.toUpperCase():o)+"="+encodeURIComponent(t[o]));return(i&&-1!==i.indexOf("?")?"&":"?")+n.join("&")}function _(t,i){return t.replace(ii,function(t,e){var n=i[e];if(void 0===n)throw new Error("No value provided for variable "+t);return"function"==typeof n&&(n=n(i)),n})}function d(t,i){for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1}function p(t){return window["webkit"+t]||window["moz"+t]||window["ms"+t]}function m(t){var i=+new Date,e=Math.max(0,16-(i-oi));return oi=i+e,window.setTimeout(t,e)}function f(t,i,n){if(!n||si!==m)return si.call(window,e(t,i));t.call(i)}function g(t){t&&ri.call(window,t)}function v(){}function y(t){if("undefined"!=typeof L&&L&&L.Mixin){t=ei(t)?t:[t];for(var i=0;i<t.length;i++)t[i]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",(new Error).stack)}}function x(t,i,e){this.x=e?Math.round(t):t,this.y=e?Math.round(i):i}function w(t,i,e){return t instanceof x?t:ei(t)?new x(t[0],t[1]):void 0===t||null===t?t:"object"==typeof t&&"x"in t&&"y"in t?new x(t.x,t.y):new x(t,i,e)}function P(t,i){if(t)for(var e=i?[t,i]:t,n=0,o=e.length;n<o;n++)this.extend(e[n])}function b(t,i){return!t||t instanceof P?t:new P(t,i)}function T(t,i){if(t)for(var e=i?[t,i]:t,n=0,o=e.length;n<o;n++)this.extend(e[n])}function z(t,i){return t instanceof T?t:new T(t,i)}function M(t,i,e){if(isNaN(t)||isNaN(i))throw new Error("Invalid LatLng object: ("+t+", "+i+")");this.lat=+t,this.lng=+i,void 0!==e&&(this.alt=+e)}function C(t,i,e){return t instanceof M?t:ei(t)&&"object"!=typeof t[0]?3===t.length?new M(t[0],t[1],t[2]):2===t.length?new M(t[0],t[1]):null:void 0===t||null===t?t:"object"==typeof t&&"lat"in t?new M(t.lat,"lng"in t?t.lng:t.lon,t.alt):void 0===i?null:new M(t,i,e)}function Z(t,i,e,n){if(ei(t))return this._a=t[0],this._b=t[1],this._c=t[2],void(this._d=t[3]);this._a=t,this._b=i,this._c=e,this._d=n}function S(t,i,e,n){return new Z(t,i,e,n)}function E(t){return document.createElementNS("http://www.w3.org/2000/svg",t)}function k(t,i){var e,n,o,s,r,a,h="";for(e=0,o=t.length;e<o;e++){for(n=0,s=(r=t[e]).length;n<s;n++)a=r[n],h+=(n?"L":"M")+a.x+" "+a.y;h+=i?Xi?"z":"x":""}return h||"M0 0"}function A(t){return navigator.userAgent.toLowerCase().indexOf(t)>=0}function I(t,i,e,n){return"touchstart"===i?O(t,e,n):"touchmove"===i?W(t,e,n):"touchend"===i&&H(t,e,n),this}function B(t,i,e){var n=t["_leaflet_"+i+e];return"touchstart"===i?t.removeEventListener(Qi,n,!1):"touchmove"===i?t.removeEventListener(te,n,!1):"touchend"===i&&(t.removeEventListener(ie,n,!1),t.removeEventListener(ee,n,!1)),this}function O(t,i,n){var o=e(function(t){if("mouse"!==t.pointerType&&t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(ne.indexOf(t.target.tagName)<0))return;$(t)}j(t,i)});t["_leaflet_touchstart"+n]=o,t.addEventListener(Qi,o,!1),se||(document.document
|
||
|
<style type="text/css">
|
||
|
img.leaflet-tile {
|
||
|
padding: 0;
|
||
|
margin: 0;
|
||
|
border-radius: 0;
|
||
|
border: none;
|
||
|
}
|
||
|
.leaflet .info {
|
||
|
padding: 6px 8px;
|
||
|
font: 14px/16px Arial, Helvetica, sans-serif;
|
||
|
background: white;
|
||
|
background: rgba(255,255,255,0.8);
|
||
|
box-shadow: 0 0 15px rgba(0,0,0,0.2);
|
||
|
border-radius: 5px;
|
||
|
}
|
||
|
.leaflet .legend {
|
||
|
line-height: 18px;
|
||
|
color: #555;
|
||
|
}
|
||
|
.leaflet .legend svg text {
|
||
|
fill: #555;
|
||
|
}
|
||
|
.leaflet .legend svg line {
|
||
|
stroke: #555;
|
||
|
}
|
||
|
.leaflet .legend i {
|
||
|
width: 18px;
|
||
|
height: 18px;
|
||
|
margin-right: 4px;
|
||
|
opacity: 0.7;
|
||
|
display: inline-block;
|
||
|
vertical-align: top;
|
||
|
|
||
|
zoom: 1;
|
||
|
*display: inline;
|
||
|
}
|
||
|
</style>
|
||
|
<script>!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s():"function"==typeof define&&define.amd?define(s):t.proj4=s()}(this,function(){"use strict";function k(t,s){if(t[s])return t[s];for(var i,a=Object.keys(t),h=s.toLowerCase().replace(H,""),e=-1;++e<a.length;)if((i=a[e]).toLowerCase().replace(H,"")===h)return t[i]}function e(t){if("string"!=typeof t)throw new Error("not a string");this.text=t.trim(),this.level=0,this.place=0,this.root=null,this.stack=[],this.currentObject=null,this.state=K}function h(t,s,i){Array.isArray(s)&&(i.unshift(s),s=null);var a=s?{}:t,h=i.reduce(function(t,s){return n(s,t),t},a);s&&(t[s]=h)}function n(t,s){if(Array.isArray(t)){var i,a=t.shift();if("PARAMETER"===a&&(a=t.shift()),1===t.length)return Array.isArray(t[0])?(s[a]={},void n(t[0],s[a])):void(s[a]=t[0]);if(t.length)if("TOWGS84"!==a){if("AXIS"===a)return a in s||(s[a]=[]),void s[a].push(t);switch(Array.isArray(a)||(s[a]={}),a){case"UNIT":case"PRIMEM":case"VERT_DATUM":return s[a]={name:t[0].toLowerCase(),convert:t[1]},void(3===t.length&&n(t[2],s[a]));case"SPHEROID":case"ELLIPSOID":return s[a]={name:t[0],a:t[1],rf:t[2]},void(4===t.length&&n(t[3],s[a]));case"PROJECTEDCRS":case"PROJCRS":case"GEOGCS":case"GEOCCS":case"PROJCS":case"LOCAL_CS":case"GEODCRS":case"GEODETICCRS":case"GEODETICDATUM":case"EDATUM":case"ENGINEERINGDATUM":case"VERT_CS":case"VERTCRS":case"VERTICALCRS":case"COMPD_CS":case"COMPOUNDCRS":case"ENGINEERINGCRS":case"ENGCRS":case"FITTED_CS":case"LOCAL_DATUM":case"DATUM":return t[0]=["name",t[0]],void h(s,a,t);default:for(i=-1;++i<t.length;)if(!Array.isArray(t[i]))return n(t,s[a]);return h(s,a,t)}}else s[a]=t;else s[a]=!0}else s[t]=!0}function r(t){return t*it}function o(e){function t(t){return t*(e.to_meter||1)}if("GEOGCS"===e.type?e.projName="longlat":"LOCAL_CS"===e.type?(e.projName="identity",e.local=!0):"object"==typeof e.PROJECTION?e.projName=Object.keys(e.PROJECTION)[0]:e.projName=e.PROJECTION,e.AXIS){for(var s="",i=0,a=e.AXIS.length;i<a;++i){var h=e.AXIS[i][0].toLowerCase();-1!==h.indexOf("north")?s+="n":-1!==h.indexOf("south")?s+="s":-1!==h.indexOf("east")?s+="e":-1!==h.indexOf("west")&&(s+="w")}2===s.length&&(s+="u"),3===s.length&&(e.axis=s)}e.UNIT&&(e.units=e.UNIT.name.toLowerCase(),"metre"===e.units&&(e.units="meter"),e.UNIT.convert&&("GEOGCS"===e.type?e.DATUM&&e.DATUM.SPHEROID&&(e.to_meter=e.UNIT.convert*e.DATUM.SPHEROID.a):e.to_meter=e.UNIT.convert));var n=e.GEOGCS;"GEOGCS"===e.type&&(n=e),n&&(n.DATUM?e.datumCode=n.DATUM.name.toLowerCase():e.datumCode=n.name.toLowerCase(),"d_"===e.datumCode.slice(0,2)&&(e.datumCode=e.datumCode.slice(2)),"new_zealand_geodetic_datum_1949"!==e.datumCode&&"new_zealand_1949"!==e.datumCode||(e.datumCode="nzgd49"),"wgs_1984"!==e.datumCode&&"world_geodetic_system_1984"!==e.datumCode||("Mercator_Auxiliary_Sphere"===e.PROJECTION&&(e.sphere=!0),e.datumCode="wgs84"),"_ferro"===e.datumCode.slice(-6)&&(e.datumCode=e.datumCode.slice(0,-6)),"_jakarta"===e.datumCode.slice(-8)&&(e.datumCode=e.datumCode.slice(0,-8)),~e.datumCode.indexOf("belge")&&(e.datumCode="rnb72"),n.DATUM&&n.DATUM.SPHEROID&&(e.ellps=n.DATUM.SPHEROID.name.replace("_19","").replace(/[Cc]larke\_18/,"clrk"),"international"===e.ellps.toLowerCase().slice(0,13)&&(e.ellps="intl"),e.a=n.DATUM.SPHEROID.a,e.rf=parseFloat(n.DATUM.SPHEROID.rf,10)),n.DATUM&&n.DATUM.TOWGS84&&(e.datum_params=n.DATUM.TOWGS84),~e.datumCode.indexOf("osgb_1936")&&(e.datumCode="osgb36"),~e.datumCode.indexOf("osni_1952")&&(e.datumCode="osni52"),(~e.datumCode.indexOf("tm65")||~e.datumCode.indexOf("geodetic_datum_of_1965"))&&(e.datumCode="ire65"),"ch1903+"===e.datumCode&&(e.datumCode="ch1903"),~e.datumCode.indexOf("israel")&&(e.datumCode="isr93")),e.b&&!isFinite(e.b)&&(e.b=e.a),[["standard_parallel_1","Standard_Parallel_1"],["standard_parallel_2","Standard_Parallel_2"],["false_easting","False_Easting"],["false_northing","False_Northing"],["central_meridian","Central_Meridian"],["latitude_of_origin","Latitude_Of_Origin"],["latitude_of_origin","Central_Parallel"],["scale_factor","Scale_Factor"],["k0","scale_factor"],["latitude_of_center",
|
||
|
<script>(function (factory) {
|
||
|
var L, proj4;
|
||
|
if (typeof define === 'function' && define.amd) {
|
||
|
// AMD
|
||
|
define(['leaflet', 'proj4'], factory);
|
||
|
} else if (typeof module === 'object' && typeof module.exports === "object") {
|
||
|
// Node/CommonJS
|
||
|
L = require('leaflet');
|
||
|
proj4 = require('proj4');
|
||
|
module.exports = factory(L, proj4);
|
||
|
} else {
|
||
|
// Browser globals
|
||
|
if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
|
||
|
throw 'Leaflet and proj4 must be loaded first';
|
||
|
factory(window.L, window.proj4);
|
||
|
}
|
||
|
}(function (L, proj4) {
|
||
|
if (proj4.__esModule && proj4.default) {
|
||
|
// If proj4 was bundled as an ES6 module, unwrap it to get
|
||
|
// to the actual main proj4 object.
|
||
|
// See discussion in https://github.com/kartena/Proj4Leaflet/pull/147
|
||
|
proj4 = proj4.default;
|
||
|
}
|
||
|
|
||
|
L.Proj = {};
|
||
|
|
||
|
L.Proj._isProj4Obj = function(a) {
|
||
|
return (typeof a.inverse !== 'undefined' &&
|
||
|
typeof a.forward !== 'undefined');
|
||
|
};
|
||
|
|
||
|
L.Proj.Projection = L.Class.extend({
|
||
|
initialize: function(code, def, bounds) {
|
||
|
var isP4 = L.Proj._isProj4Obj(code);
|
||
|
this._proj = isP4 ? code : this._projFromCodeDef(code, def);
|
||
|
this.bounds = isP4 ? def : bounds;
|
||
|
},
|
||
|
|
||
|
project: function (latlng) {
|
||
|
var point = this._proj.forward([latlng.lng, latlng.lat]);
|
||
|
return new L.Point(point[0], point[1]);
|
||
|
},
|
||
|
|
||
|
unproject: function (point, unbounded) {
|
||
|
var point2 = this._proj.inverse([point.x, point.y]);
|
||
|
return new L.LatLng(point2[1], point2[0], unbounded);
|
||
|
},
|
||
|
|
||
|
_projFromCodeDef: function(code, def) {
|
||
|
if (def) {
|
||
|
proj4.defs(code, def);
|
||
|
} else if (proj4.defs[code] === undefined) {
|
||
|
var urn = code.split(':');
|
||
|
if (urn.length > 3) {
|
||
|
code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
|
||
|
}
|
||
|
if (proj4.defs[code] === undefined) {
|
||
|
throw 'No projection definition for code ' + code;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return proj4(code);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Proj.CRS = L.Class.extend({
|
||
|
includes: L.CRS,
|
||
|
|
||
|
options: {
|
||
|
transformation: new L.Transformation(1, 0, -1, 0)
|
||
|
},
|
||
|
|
||
|
initialize: function(a, b, c) {
|
||
|
var code,
|
||
|
proj,
|
||
|
def,
|
||
|
options;
|
||
|
|
||
|
if (L.Proj._isProj4Obj(a)) {
|
||
|
proj = a;
|
||
|
code = proj.srsCode;
|
||
|
options = b || {};
|
||
|
|
||
|
this.projection = new L.Proj.Projection(proj, options.bounds);
|
||
|
} else {
|
||
|
code = a;
|
||
|
def = b;
|
||
|
options = c || {};
|
||
|
this.projection = new L.Proj.Projection(code, def, options.bounds);
|
||
|
}
|
||
|
|
||
|
L.Util.setOptions(this, options);
|
||
|
this.code = code;
|
||
|
this.transformation = this.options.transformation;
|
||
|
|
||
|
if (this.options.origin) {
|
||
|
this.transformation =
|
||
|
new L.Transformation(1, -this.options.origin[0],
|
||
|
-1, this.options.origin[1]);
|
||
|
}
|
||
|
|
||
|
if (this.options.scales) {
|
||
|
this._scales = this.options.scales;
|
||
|
} else if (this.options.resolutions) {
|
||
|
this._scales = [];
|
||
|
for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
|
||
|
if (this.options.resolutions[i]) {
|
||
|
this._scales[i] = 1 / this.options.resolutions[i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.infinite = !this.options.bounds;
|
||
|
|
||
|
},
|
||
|
|
||
|
scale: function(zoom) {
|
||
|
var iZoom = Math.floor(zoom),
|
||
|
baseScale,
|
||
|
nextScale,
|
||
|
scaleDiff,
|
||
|
zDiff;
|
||
|
if (zoom === iZoom) {
|
||
|
return this._scales[zoom];
|
||
|
} else {
|
||
|
// Non-integer zoom, interpolate
|
||
|
baseScale = this._scales[iZoom];
|
||
|
nextScale = this._scales[iZoom + 1];
|
||
|
scaleDiff = nextScale - baseScale;
|
||
|
zDiff = (zoom - iZoom);
|
||
|
return baseScale + scaleDiff * zDiff;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
zoom: function(scale) {
|
||
|
// Find closest number in this._scales, down
|
||
|
var downScale = this._closestElement(this._scales, scale),
|
||
|
downZoom = this._scales.indexOf(downScale),
|
||
|
nextScale,
|
||
|
nextZoom,
|
||
|
scaleDiff;
|
||
|
// Check if scale is downScale => return array index
|
||
|
if (scale === downScale) {
|
||
|
return downZoom;
|
||
|
}
|
||
|
if (downScale === undefined) {
|
||
|
return -Infinity;
|
||
|
}
|
||
|
// Interpolate
|
||
|
nextZoom = downZoom + 1;
|
||
|
nextScale = this._scales[nextZoom];
|
||
|
if (nextScale === undefined) {
|
||
|
return Infinity;
|
||
|
}
|
||
|
scaleDiff = nextScale - downScale;
|
||
|
return (scale - downScale) / scaleDiff + downZoom;
|
||
|
},
|
||
|
|
||
|
distance: L.CRS.Earth.distance,
|
||
|
|
||
|
R: L.CRS.Earth.R,
|
||
|
|
||
|
/* Get the closest lowest element in an array */
|
||
|
_closestElement: function(array, element) {
|
||
|
var low;
|
||
|
for (var i = array.length; i--;) {
|
||
|
if (array[i] <= element && (low === undefined || low < array[i])) {
|
||
|
low = array[i];
|
||
|
}
|
||
|
}
|
||
|
return low;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Proj.GeoJSON = L.GeoJSON.extend({
|
||
|
initialize: function(geojson, options) {
|
||
|
this._callLevel = 0;
|
||
|
L.GeoJSON.prototype.initialize.call(this, geojson, options);
|
||
|
},
|
||
|
|
||
|
addData: function(geojson) {
|
||
|
var crs;
|
||
|
|
||
|
if (geojson) {
|
||
|
if (geojson.crs && geojson.crs.type === 'name') {
|
||
|
crs = new L.Proj.CRS(geojson.crs.properties.name);
|
||
|
} else if (geojson.crs && geojson.crs.type) {
|
||
|
crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
|
||
|
}
|
||
|
|
||
|
if (crs !== undefined) {
|
||
|
this.options.coordsToLatLng = function(coords) {
|
||
|
var point = L.point(coords[0], coords[1]);
|
||
|
return crs.projection.unproject(point);
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Base class' addData might call us recursively, but
|
||
|
// CRS shouldn't be cleared in that case, since CRS applies
|
||
|
// to the whole GeoJSON, inluding sub-features.
|
||
|
this._callLevel++;
|
||
|
try {
|
||
|
L.GeoJSON.prototype.addData.call(this, geojson);
|
||
|
} finally {
|
||
|
this._callLevel--;
|
||
|
if (this._callLevel === 0) {
|
||
|
delete this.options.coordsToLatLng;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Proj.geoJson = function(geojson, options) {
|
||
|
return new L.Proj.GeoJSON(geojson, options);
|
||
|
};
|
||
|
|
||
|
L.Proj.ImageOverlay = L.ImageOverlay.extend({
|
||
|
initialize: function (url, bounds, options) {
|
||
|
L.ImageOverlay.prototype.initialize.call(this, url, null, options);
|
||
|
this._projectedBounds = bounds;
|
||
|
},
|
||
|
|
||
|
// Danger ahead: Overriding internal methods in Leaflet.
|
||
|
// Decided to do this rather than making a copy of L.ImageOverlay
|
||
|
// and doing very tiny modifications to it.
|
||
|
// Future will tell if this was wise or not.
|
||
|
_animateZoom: function (event) {
|
||
|
var scale = this._map.getZoomScale(event.zoom);
|
||
|
var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
|
||
|
var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
|
||
|
|
||
|
L.DomUtil.setTransform(this._image, offset, scale);
|
||
|
},
|
||
|
|
||
|
_reset: function () {
|
||
|
var zoom = this._map.getZoom();
|
||
|
var pixelOrigin = this._map.getPixelOrigin();
|
||
|
var bounds = L.bounds(
|
||
|
this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
|
||
|
this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
|
||
|
);
|
||
|
var size = bounds.getSize();
|
||
|
|
||
|
L.DomUtil.setPosition(this._image, bounds.min);
|
||
|
this._image.style.width = size.x + 'px';
|
||
|
this._image.style.height = size.y + 'px';
|
||
|
},
|
||
|
|
||
|
_projectedToNewLayerPoint: function (point, zoom, center) {
|
||
|
var viewHalf = this._map.getSize()._divideBy(2);
|
||
|
var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
|
||
|
var topLeft = newTopLeft.add(this._map._getMapPanePos());
|
||
|
|
||
|
return this._transform(point, zoom)._subtract(topLeft);
|
||
|
},
|
||
|
|
||
|
_transform: function (point, zoom) {
|
||
|
var crs = this._map.options.crs;
|
||
|
var transformation = crs.transformation;
|
||
|
var scale = crs.scale(zoom);
|
||
|
|
||
|
return transformation.transform(point, scale);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
L.Proj.imageOverlay = function (url, bounds, options) {
|
||
|
return new L.Proj.ImageOverlay(url, bounds, options);
|
||
|
};
|
||
|
|
||
|
return L.Proj;
|
||
|
}));
|
||
|
</script>
|
||
|
<style type="text/css">.leaflet-tooltip.leaflet-tooltip-text-only,
|
||
|
.leaflet-tooltip.leaflet-tooltip-text-only:before,
|
||
|
.leaflet-tooltip.leaflet-tooltip-text-only:after {
|
||
|
background: none;
|
||
|
border: none;
|
||
|
box-shadow: none;
|
||
|
}
|
||
|
.leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-left {
|
||
|
margin-left: 5px;
|
||
|
}
|
||
|
.leaflet-tooltip.leaflet-tooltip-text-only.leaflet-tooltip-right {
|
||
|
margin-left: -5px;
|
||
|
}
|
||
|
.leaflet-tooltip:after {
|
||
|
border-right: 6px solid transparent;
|
||
|
|
||
|
}
|
||
|
.leaflet-popup-pane .leaflet-popup-tip-container {
|
||
|
|
||
|
pointer-events: all;
|
||
|
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
.leaflet-map-pane {
|
||
|
z-index: auto;
|
||
|
}
|
||
|
|
||
|
.leaflet-container .leaflet-right-pane img,
|
||
|
.leaflet-container .leaflet-left-pane img {
|
||
|
max-width: none !important;
|
||
|
max-height: none !important;
|
||
|
}
|
||
|
</style>
|
||
|
<script>(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = undefined;
|
||
|
|
||
|
var _util = require("./util");
|
||
|
|
||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
||
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||
|
|
||
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||
|
|
||
|
var ClusterLayerStore = /*#__PURE__*/function () {
|
||
|
function ClusterLayerStore(group) {
|
||
|
_classCallCheck(this, ClusterLayerStore);
|
||
|
|
||
|
this._layers = {};
|
||
|
this._group = group;
|
||
|
}
|
||
|
|
||
|
_createClass(ClusterLayerStore, [{
|
||
|
key: "add",
|
||
|
value: function add(layer, id) {
|
||
|
if (typeof id !== "undefined" && id !== null) {
|
||
|
if (this._layers[id]) {
|
||
|
this._group.removeLayer(this._layers[id]);
|
||
|
}
|
||
|
|
||
|
this._layers[id] = layer;
|
||
|
}
|
||
|
|
||
|
this._group.addLayer(layer);
|
||
|
}
|
||
|
}, {
|
||
|
key: "remove",
|
||
|
value: function remove(id) {
|
||
|
if (typeof id === "undefined" || id === null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
id = (0, _util.asArray)(id);
|
||
|
|
||
|
for (var i = 0; i < id.length; i++) {
|
||
|
if (this._layers[id[i]]) {
|
||
|
this._group.removeLayer(this._layers[id[i]]);
|
||
|
|
||
|
delete this._layers[id[i]];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: "clear",
|
||
|
value: function clear() {
|
||
|
this._layers = {};
|
||
|
|
||
|
this._group.clearLayers();
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return ClusterLayerStore;
|
||
|
}();
|
||
|
|
||
|
exports["default"] = ClusterLayerStore;
|
||
|
|
||
|
|
||
|
},{"./util":17}],2:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
|
||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
||
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||
|
|
||
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||
|
|
||
|
var ControlStore = /*#__PURE__*/function () {
|
||
|
function ControlStore(map) {
|
||
|
_classCallCheck(this, ControlStore);
|
||
|
|
||
|
this._controlsNoId = [];
|
||
|
this._controlsById = {};
|
||
|
this._map = map;
|
||
|
}
|
||
|
|
||
|
_createClass(ControlStore, [{
|
||
|
key: "add",
|
||
|
value: function add(control, id, html) {
|
||
|
if (typeof id !== "undefined" && id !== null) {
|
||
|
if (this._controlsById[id]) {
|
||
|
this._map.removeControl(this._controlsById[id]);
|
||
|
}
|
||
|
|
||
|
this._controlsById[id] = control;
|
||
|
} else {
|
||
|
this._controlsNoId.push(control);
|
||
|
}
|
||
|
|
||
|
this._map.addControl(control);
|
||
|
}
|
||
|
}, {
|
||
|
key: "get",
|
||
|
value: function get(id) {
|
||
|
var control = null;
|
||
|
|
||
|
if (this._controlsById[id]) {
|
||
|
control = this._controlsById[id];
|
||
|
}
|
||
|
|
||
|
return control;
|
||
|
}
|
||
|
}, {
|
||
|
key: "remove",
|
||
|
value: function remove(id) {
|
||
|
if (this._controlsById[id]) {
|
||
|
var control = this._controlsById[id];
|
||
|
|
||
|
this._map.removeControl(control);
|
||
|
|
||
|
delete this._controlsById[id];
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: "clear",
|
||
|
value: function clear() {
|
||
|
for (var i = 0; i < this._controlsNoId.length; i++) {
|
||
|
var control = this._controlsNoId[i];
|
||
|
|
||
|
this._map.removeControl(control);
|
||
|
}
|
||
|
|
||
|
this._controlsNoId = [];
|
||
|
|
||
|
for (var key in this._controlsById) {
|
||
|
var _control = this._controlsById[key];
|
||
|
|
||
|
this._map.removeControl(_control);
|
||
|
}
|
||
|
|
||
|
this._controlsById = {};
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return ControlStore;
|
||
|
}();
|
||
|
|
||
|
exports["default"] = ControlStore;
|
||
|
|
||
|
|
||
|
},{}],3:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.getCRS = getCRS;
|
||
|
|
||
|
var _leaflet = require("./global/leaflet");
|
||
|
|
||
|
var _leaflet2 = _interopRequireDefault(_leaflet);
|
||
|
|
||
|
var _proj4leaflet = require("./global/proj4leaflet");
|
||
|
|
||
|
var _proj4leaflet2 = _interopRequireDefault(_proj4leaflet);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||
|
|
||
|
// Helper function to instanciate a ICRS instance.
|
||
|
function getCRS(crsOptions) {
|
||
|
var crs = _leaflet2["default"].CRS.EPSG3857; // Default Spherical Mercator
|
||
|
|
||
|
switch (crsOptions.crsClass) {
|
||
|
case "L.CRS.EPSG3857":
|
||
|
crs = _leaflet2["default"].CRS.EPSG3857;
|
||
|
break;
|
||
|
|
||
|
case "L.CRS.EPSG4326":
|
||
|
crs = _leaflet2["default"].CRS.EPSG4326;
|
||
|
break;
|
||
|
|
||
|
case "L.CRS.EPSG3395":
|
||
|
crs = _leaflet2["default"].CRS.EPSG3395;
|
||
|
break;
|
||
|
|
||
|
case "L.CRS.Simple":
|
||
|
crs = _leaflet2["default"].CRS.Simple;
|
||
|
break;
|
||
|
|
||
|
case "L.Proj.CRS":
|
||
|
if (crsOptions.options && crsOptions.options.bounds) {
|
||
|
crsOptions.options.bounds = _leaflet2["default"].bounds(crsOptions.options.bounds);
|
||
|
}
|
||
|
|
||
|
if (crsOptions.options && crsOptions.options.transformation) {
|
||
|
crsOptions.options.transformation = new _leaflet2["default"].Transformation(crsOptions.options.transformation[0], crsOptions.options.transformation[1], crsOptions.options.transformation[2], crsOptions.options.transformation[3]);
|
||
|
}
|
||
|
|
||
|
crs = new _proj4leaflet2["default"].CRS(crsOptions.code, crsOptions.proj4def, crsOptions.options);
|
||
|
break;
|
||
|
|
||
|
case "L.Proj.CRS.TMS":
|
||
|
if (crsOptions.options && crsOptions.options.bounds) {
|
||
|
crsOptions.options.bounds = _leaflet2["default"].bounds(crsOptions.options.bounds);
|
||
|
}
|
||
|
|
||
|
if (crsOptions.options && crsOptions.options.transformation) {
|
||
|
crsOptions.options.transformation = _leaflet2["default"].Transformation(crsOptions.options.transformation[0], crsOptions.options.transformation[1], crsOptions.options.transformation[2], crsOptions.options.transformation[3]);
|
||
|
} // L.Proj.CRS.TMS is deprecated as of Leaflet 1.x, fall back to L.Proj.CRS
|
||
|
//crs = new Proj4Leaflet.CRS.TMS(crsOptions.code, crsOptions.proj4def, crsOptions.projectedBounds, crsOptions.options);
|
||
|
|
||
|
|
||
|
crs = new _proj4leaflet2["default"].CRS(crsOptions.code, crsOptions.proj4def, crsOptions.options);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return crs;
|
||
|
}
|
||
|
|
||
|
|
||
|
},{"./global/leaflet":10,"./global/proj4leaflet":11}],4:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = undefined;
|
||
|
|
||
|
var _util = require("./util");
|
||
|
|
||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
||
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||
|
|
||
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||
|
|
||
|
var DataFrame = /*#__PURE__*/function () {
|
||
|
function DataFrame() {
|
||
|
_classCallCheck(this, DataFrame);
|
||
|
|
||
|
this.columns = [];
|
||
|
this.colnames = [];
|
||
|
this.colstrict = [];
|
||
|
this.effectiveLength = 0;
|
||
|
this.colindices = {};
|
||
|
}
|
||
|
|
||
|
_createClass(DataFrame, [{
|
||
|
key: "_updateCachedProperties",
|
||
|
value: function _updateCachedProperties() {
|
||
|
var _this = this;
|
||
|
|
||
|
this.effectiveLength = 0;
|
||
|
this.colindices = {};
|
||
|
this.columns.forEach(function (column, i) {
|
||
|
_this.effectiveLength = Math.max(_this.effectiveLength, column.length);
|
||
|
_this.colindices[_this.colnames[i]] = i;
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: "_colIndex",
|
||
|
value: function _colIndex(colname) {
|
||
|
var index = this.colindices[colname];
|
||
|
if (typeof index === "undefined") return -1;
|
||
|
return index;
|
||
|
}
|
||
|
}, {
|
||
|
key: "col",
|
||
|
value: function col(name, values, strict) {
|
||
|
if (typeof name !== "string") throw new Error("Invalid column name \"" + name + "\"");
|
||
|
|
||
|
var index = this._colIndex(name);
|
||
|
|
||
|
if (arguments.length === 1) {
|
||
|
if (index < 0) return null;else return (0, _util.recycle)(this.columns[index], this.effectiveLength);
|
||
|
}
|
||
|
|
||
|
if (index < 0) {
|
||
|
index = this.colnames.length;
|
||
|
this.colnames.push(name);
|
||
|
}
|
||
|
|
||
|
this.columns[index] = (0, _util.asArray)(values);
|
||
|
this.colstrict[index] = !!strict; // TODO: Validate strictness (ensure lengths match up with other stricts)
|
||
|
|
||
|
this._updateCachedProperties();
|
||
|
|
||
|
return this;
|
||
|
}
|
||
|
}, {
|
||
|
key: "cbind",
|
||
|
value: function cbind(obj, strict) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
Object.keys(obj).forEach(function (name) {
|
||
|
var coldata = obj[name];
|
||
|
|
||
|
_this2.col(name, coldata);
|
||
|
});
|
||
|
return this;
|
||
|
}
|
||
|
}, {
|
||
|
key: "get",
|
||
|
value: function get(row, col, missingOK) {
|
||
|
var _this3 = this;
|
||
|
|
||
|
if (row > this.effectiveLength) throw new Error("Row argument was out of bounds: " + row + " > " + this.effectiveLength);
|
||
|
var colIndex = -1;
|
||
|
|
||
|
if (typeof col === "undefined") {
|
||
|
var rowData = {};
|
||
|
this.colnames.forEach(function (name, i) {
|
||
|
rowData[name] = _this3.columns[i][row % _this3.columns[i].length];
|
||
|
});
|
||
|
return rowData;
|
||
|
} else if (typeof col === "string") {
|
||
|
colIndex = this._colIndex(col);
|
||
|
} else if (typeof col === "number") {
|
||
|
colIndex = col;
|
||
|
}
|
||
|
|
||
|
if (colIndex < 0 || colIndex > this.columns.length) {
|
||
|
if (missingOK) return void 0;else throw new Error("Unknown column index: " + col);
|
||
|
}
|
||
|
|
||
|
return this.columns[colIndex][row % this.columns[colIndex].length];
|
||
|
}
|
||
|
}, {
|
||
|
key: "nrow",
|
||
|
value: function nrow() {
|
||
|
return this.effectiveLength;
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return DataFrame;
|
||
|
}();
|
||
|
|
||
|
exports["default"] = DataFrame;
|
||
|
|
||
|
|
||
|
},{"./util":17}],5:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
var _leaflet = require("./global/leaflet");
|
||
|
|
||
|
var _leaflet2 = _interopRequireDefault(_leaflet);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||
|
|
||
|
// In RMarkdown's self-contained mode, we don't have a way to carry around the
|
||
|
// images that Leaflet needs but doesn't load into the page. Instead, we'll use
|
||
|
// the unpkg CDN.
|
||
|
if (typeof _leaflet2["default"].Icon.Default.imagePath === "undefined") {
|
||
|
_leaflet2["default"].Icon.Default.imagePath = "https://unpkg.com/leaflet@1.3.1/dist/images/";
|
||
|
}
|
||
|
|
||
|
|
||
|
},{"./global/leaflet":10}],6:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
var _leaflet = require("./global/leaflet");
|
||
|
|
||
|
var _leaflet2 = _interopRequireDefault(_leaflet);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||
|
|
||
|
// add texxtsize, textOnly, and style
|
||
|
_leaflet2["default"].Tooltip.prototype.options.textsize = "10px";
|
||
|
_leaflet2["default"].Tooltip.prototype.options.textOnly = false;
|
||
|
_leaflet2["default"].Tooltip.prototype.options.style = null; // copy original layout to not completely stomp it.
|
||
|
|
||
|
var initLayoutOriginal = _leaflet2["default"].Tooltip.prototype._initLayout;
|
||
|
|
||
|
_leaflet2["default"].Tooltip.prototype._initLayout = function () {
|
||
|
initLayoutOriginal.call(this);
|
||
|
this._container.style.fontSize = this.options.textsize;
|
||
|
|
||
|
if (this.options.textOnly) {
|
||
|
_leaflet2["default"].DomUtil.addClass(this._container, "leaflet-tooltip-text-only");
|
||
|
}
|
||
|
|
||
|
if (this.options.style) {
|
||
|
for (var property in this.options.style) {
|
||
|
this._container.style[property] = this.options.style[property];
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
},{"./global/leaflet":10}],7:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
var _leaflet = require("./global/leaflet");
|
||
|
|
||
|
var _leaflet2 = _interopRequireDefault(_leaflet);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||
|
|
||
|
var protocolRegex = /^\/\//;
|
||
|
|
||
|
var upgrade_protocol = function upgrade_protocol(urlTemplate) {
|
||
|
if (protocolRegex.test(urlTemplate)) {
|
||
|
if (window.location.protocol === "file:") {
|
||
|
// if in a local file, support http
|
||
|
// http should auto upgrade if necessary
|
||
|
urlTemplate = "http:" + urlTemplate;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return urlTemplate;
|
||
|
};
|
||
|
|
||
|
var originalLTileLayerInitialize = _leaflet2["default"].TileLayer.prototype.initialize;
|
||
|
|
||
|
_leaflet2["default"].TileLayer.prototype.initialize = function (urlTemplate, options) {
|
||
|
urlTemplate = upgrade_protocol(urlTemplate);
|
||
|
originalLTileLayerInitialize.call(this, urlTemplate, options);
|
||
|
};
|
||
|
|
||
|
var originalLTileLayerWMSInitialize = _leaflet2["default"].TileLayer.WMS.prototype.initialize;
|
||
|
|
||
|
_leaflet2["default"].TileLayer.WMS.prototype.initialize = function (urlTemplate, options) {
|
||
|
urlTemplate = upgrade_protocol(urlTemplate);
|
||
|
originalLTileLayerWMSInitialize.call(this, urlTemplate, options);
|
||
|
};
|
||
|
|
||
|
|
||
|
},{"./global/leaflet":10}],8:[function(require,module,exports){
|
||
|
(function (global){(function (){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = global.HTMLWidgets;
|
||
|
|
||
|
|
||
|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
|
},{}],9:[function(require,module,exports){
|
||
|
(function (global){(function (){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = global.jQuery;
|
||
|
|
||
|
|
||
|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
|
},{}],10:[function(require,module,exports){
|
||
|
(function (global){(function (){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = global.L;
|
||
|
|
||
|
|
||
|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
|
},{}],11:[function(require,module,exports){
|
||
|
(function (global){(function (){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = global.L.Proj;
|
||
|
|
||
|
|
||
|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
|
},{}],12:[function(require,module,exports){
|
||
|
(function (global){(function (){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = global.Shiny;
|
||
|
|
||
|
|
||
|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
|
},{}],13:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
var _jquery = require("./global/jquery");
|
||
|
|
||
|
var _jquery2 = _interopRequireDefault(_jquery);
|
||
|
|
||
|
var _leaflet = require("./global/leaflet");
|
||
|
|
||
|
var _leaflet2 = _interopRequireDefault(_leaflet);
|
||
|
|
||
|
var _shiny = require("./global/shiny");
|
||
|
|
||
|
var _shiny2 = _interopRequireDefault(_shiny);
|
||
|
|
||
|
var _htmlwidgets = require("./global/htmlwidgets");
|
||
|
|
||
|
var _htmlwidgets2 = _interopRequireDefault(_htmlwidgets);
|
||
|
|
||
|
var _util = require("./util");
|
||
|
|
||
|
var _crs_utils = require("./crs_utils");
|
||
|
|
||
|
var _controlStore = require("./control-store");
|
||
|
|
||
|
var _controlStore2 = _interopRequireDefault(_controlStore);
|
||
|
|
||
|
var _layerManager = require("./layer-manager");
|
||
|
|
||
|
var _layerManager2 = _interopRequireDefault(_layerManager);
|
||
|
|
||
|
var _methods = require("./methods");
|
||
|
|
||
|
var _methods2 = _interopRequireDefault(_methods);
|
||
|
|
||
|
require("./fixup-default-icon");
|
||
|
|
||
|
require("./fixup-default-tooltip");
|
||
|
|
||
|
require("./fixup-url-protocol");
|
||
|
|
||
|
var _dataframe = require("./dataframe");
|
||
|
|
||
|
var _dataframe2 = _interopRequireDefault(_dataframe);
|
||
|
|
||
|
var _clusterLayerStore = require("./cluster-layer-store");
|
||
|
|
||
|
var _clusterLayerStore2 = _interopRequireDefault(_clusterLayerStore);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||
|
|
||
|
window.LeafletWidget = {};
|
||
|
window.LeafletWidget.utils = {};
|
||
|
|
||
|
var methods = window.LeafletWidget.methods = _jquery2["default"].extend({}, _methods2["default"]);
|
||
|
|
||
|
window.LeafletWidget.DataFrame = _dataframe2["default"];
|
||
|
window.LeafletWidget.ClusterLayerStore = _clusterLayerStore2["default"];
|
||
|
window.LeafletWidget.utils.getCRS = _crs_utils.getCRS; // Send updated bounds back to app. Takes a leaflet event object as input.
|
||
|
|
||
|
function updateBounds(map) {
|
||
|
var id = map.getContainer().id;
|
||
|
var bounds = map.getBounds();
|
||
|
|
||
|
_shiny2["default"].onInputChange(id + "_bounds", {
|
||
|
north: bounds.getNorthEast().lat,
|
||
|
east: bounds.getNorthEast().lng,
|
||
|
south: bounds.getSouthWest().lat,
|
||
|
west: bounds.getSouthWest().lng
|
||
|
});
|
||
|
|
||
|
_shiny2["default"].onInputChange(id + "_center", {
|
||
|
lng: map.getCenter().lng,
|
||
|
lat: map.getCenter().lat
|
||
|
});
|
||
|
|
||
|
_shiny2["default"].onInputChange(id + "_zoom", map.getZoom());
|
||
|
}
|
||
|
|
||
|
function preventUnintendedZoomOnScroll(map) {
|
||
|
// Prevent unwanted scroll capturing. Similar in purpose to
|
||
|
// https://github.com/CliffCloud/Leaflet.Sleep but with a
|
||
|
// different set of heuristics.
|
||
|
// The basic idea is that when a mousewheel/DOMMouseScroll
|
||
|
// event is seen, we disable scroll wheel zooming until the
|
||
|
// user moves their mouse cursor or clicks on the map. This
|
||
|
// is slightly trickier than just listening for mousemove,
|
||
|
// because mousemove is fired when the page is scrolled,
|
||
|
// even if the user did not physically move the mouse. We
|
||
|
// handle this by examining the mousemove event's screenX
|
||
|
// and screenY properties; if they change, we know it's a
|
||
|
// "true" move.
|
||
|
// lastScreen can never be null, but its x and y can.
|
||
|
var lastScreen = {
|
||
|
x: null,
|
||
|
y: null
|
||
|
};
|
||
|
(0, _jquery2["default"])(document).on("mousewheel DOMMouseScroll", "*", function (e) {
|
||
|
// Disable zooming (until the mouse moves or click)
|
||
|
map.scrollWheelZoom.disable(); // Any mousemove events at this screen position will be ignored.
|
||
|
|
||
|
lastScreen = {
|
||
|
x: e.originalEvent.screenX,
|
||
|
y: e.originalEvent.screenY
|
||
|
};
|
||
|
});
|
||
|
(0, _jquery2["default"])(document).on("mousemove", "*", function (e) {
|
||
|
// Did the mouse really move?
|
||
|
if (map.options.scrollWheelZoom) {
|
||
|
if (lastScreen.x !== null && e.screenX !== lastScreen.x || e.screenY !== lastScreen.y) {
|
||
|
// It really moved. Enable zooming.
|
||
|
map.scrollWheelZoom.enable();
|
||
|
lastScreen = {
|
||
|
x: null,
|
||
|
y: null
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
(0, _jquery2["default"])(document).on("mousedown", ".leaflet", function (e) {
|
||
|
// Clicking always enables zooming.
|
||
|
if (map.options.scrollWheelZoom) {
|
||
|
map.scrollWheelZoom.enable();
|
||
|
lastScreen = {
|
||
|
x: null,
|
||
|
y: null
|
||
|
};
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
_htmlwidgets2["default"].widget({
|
||
|
name: "leaflet",
|
||
|
type: "output",
|
||
|
factory: function factory(el, width, height) {
|
||
|
var map = null;
|
||
|
return {
|
||
|
// we need to store our map in our returned object.
|
||
|
getMap: function getMap() {
|
||
|
return map;
|
||
|
},
|
||
|
renderValue: function renderValue(data) {
|
||
|
// Create an appropriate CRS Object if specified
|
||
|
if (data && data.options && data.options.crs) {
|
||
|
data.options.crs = (0, _crs_utils.getCRS)(data.options.crs);
|
||
|
} // As per https://github.com/rstudio/leaflet/pull/294#discussion_r79584810
|
||
|
|
||
|
|
||
|
if (map) {
|
||
|
map.remove();
|
||
|
|
||
|
map = function () {
|
||
|
return;
|
||
|
}(); // undefine map
|
||
|
|
||
|
}
|
||
|
|
||
|
if (data.options.mapFactory && typeof data.options.mapFactory === "function") {
|
||
|
map = data.options.mapFactory(el, data.options);
|
||
|
} else {
|
||
|
map = _leaflet2["default"].map(el, data.options);
|
||
|
}
|
||
|
|
||
|
preventUnintendedZoomOnScroll(map); // Store some state in the map object
|
||
|
|
||
|
map.leafletr = {
|
||
|
// Has the map ever rendered successfully?
|
||
|
hasRendered: false,
|
||
|
// Data to be rendered when resize is called with area != 0
|
||
|
pendingRenderData: null
|
||
|
}; // Check if the map is rendered statically (no output binding)
|
||
|
|
||
|
if (_htmlwidgets2["default"].shinyMode && /\bshiny-bound-output\b/.test(el.className)) {
|
||
|
map.id = el.id; // Store the map on the element so we can find it later by ID
|
||
|
|
||
|
(0, _jquery2["default"])(el).data("leaflet-map", map); // When the map is clicked, send the coordinates back to the app
|
||
|
|
||
|
map.on("click", function (e) {
|
||
|
_shiny2["default"].onInputChange(map.id + "_click", {
|
||
|
lat: e.latlng.lat,
|
||
|
lng: e.latlng.lng,
|
||
|
".nonce": Math.random() // Force reactivity if lat/lng hasn't changed
|
||
|
|
||
|
});
|
||
|
});
|
||
|
var groupTimerId = null;
|
||
|
map.on("moveend", function (e) {
|
||
|
updateBounds(e.target);
|
||
|
}).on("layeradd layerremove", function (e) {
|
||
|
// If the layer that's coming or going is a group we created, tell
|
||
|
// the server.
|
||
|
if (map.layerManager.getGroupNameFromLayerGroup(e.layer)) {
|
||
|
// But to avoid chattiness, coalesce events
|
||
|
if (groupTimerId) {
|
||
|
clearTimeout(groupTimerId);
|
||
|
groupTimerId = null;
|
||
|
}
|
||
|
|
||
|
groupTimerId = setTimeout(function () {
|
||
|
groupTimerId = null;
|
||
|
|
||
|
_shiny2["default"].onInputChange(map.id + "_groups", map.layerManager.getVisibleGroups());
|
||
|
}, 100);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
this.doRenderValue(data, map);
|
||
|
},
|
||
|
doRenderValue: function doRenderValue(data, map) {
|
||
|
// Leaflet does not behave well when you set up a bunch of layers when
|
||
|
// the map is not visible (width/height == 0). Popups get misaligned
|
||
|
// relative to their owning markers, and the fitBounds calculations
|
||
|
// are off. Therefore we wait until the map is actually showing to
|
||
|
// render the value (we rely on the resize() callback being invoked
|
||
|
// at the appropriate time).
|
||
|
if (el.offsetWidth === 0 || el.offsetHeight === 0) {
|
||
|
map.leafletr.pendingRenderData = data;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
map.leafletr.pendingRenderData = null; // Merge data options into defaults
|
||
|
|
||
|
var options = _jquery2["default"].extend({
|
||
|
zoomToLimits: "always"
|
||
|
}, data.options);
|
||
|
|
||
|
if (!map.layerManager) {
|
||
|
map.controls = new _controlStore2["default"](map);
|
||
|
map.layerManager = new _layerManager2["default"](map);
|
||
|
} else {
|
||
|
map.controls.clear();
|
||
|
map.layerManager.clear();
|
||
|
}
|
||
|
|
||
|
var explicitView = false;
|
||
|
|
||
|
if (data.setView) {
|
||
|
explicitView = true;
|
||
|
map.setView.apply(map, data.setView);
|
||
|
}
|
||
|
|
||
|
if (data.fitBounds) {
|
||
|
explicitView = true;
|
||
|
methods.fitBounds.apply(map, data.fitBounds);
|
||
|
}
|
||
|
|
||
|
if (data.flyTo) {
|
||
|
if (!explicitView && !map.leafletr.hasRendered) {
|
||
|
// must be done to give a initial starting point
|
||
|
map.fitWorld();
|
||
|
}
|
||
|
|
||
|
explicitView = true;
|
||
|
map.flyTo.apply(map, data.flyTo);
|
||
|
}
|
||
|
|
||
|
if (data.flyToBounds) {
|
||
|
if (!explicitView && !map.leafletr.hasRendered) {
|
||
|
// must be done to give a initial starting point
|
||
|
map.fitWorld();
|
||
|
}
|
||
|
|
||
|
explicitView = true;
|
||
|
methods.flyToBounds.apply(map, data.flyToBounds);
|
||
|
}
|
||
|
|
||
|
if (data.options.center) {
|
||
|
explicitView = true;
|
||
|
} // Returns true if the zoomToLimits option says that the map should be
|
||
|
// zoomed to map elements.
|
||
|
|
||
|
|
||
|
function needsZoom() {
|
||
|
return options.zoomToLimits === "always" || options.zoomToLimits === "first" && !map.leafletr.hasRendered;
|
||
|
}
|
||
|
|
||
|
if (!explicitView && needsZoom() && !map.getZoom()) {
|
||
|
if (data.limits && !_jquery2["default"].isEmptyObject(data.limits)) {
|
||
|
// Use the natural limits of what's being drawn on the map
|
||
|
// If the size of the bounding box is 0, leaflet gets all weird
|
||
|
var pad = 0.006;
|
||
|
|
||
|
if (data.limits.lat[0] === data.limits.lat[1]) {
|
||
|
data.limits.lat[0] = data.limits.lat[0] - pad;
|
||
|
data.limits.lat[1] = data.limits.lat[1] + pad;
|
||
|
}
|
||
|
|
||
|
if (data.limits.lng[0] === data.limits.lng[1]) {
|
||
|
data.limits.lng[0] = data.limits.lng[0] - pad;
|
||
|
data.limits.lng[1] = data.limits.lng[1] + pad;
|
||
|
}
|
||
|
|
||
|
map.fitBounds([[data.limits.lat[0], data.limits.lng[0]], [data.limits.lat[1], data.limits.lng[1]]]);
|
||
|
} else {
|
||
|
map.fitWorld();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (var i = 0; data.calls && i < data.calls.length; i++) {
|
||
|
var call = data.calls[i];
|
||
|
if (methods[call.method]) methods[call.method].apply(map, call.args);else (0, _util.log)("Unknown method " + call.method);
|
||
|
}
|
||
|
|
||
|
map.leafletr.hasRendered = true;
|
||
|
|
||
|
if (_htmlwidgets2["default"].shinyMode) {
|
||
|
setTimeout(function () {
|
||
|
updateBounds(map);
|
||
|
}, 1);
|
||
|
}
|
||
|
},
|
||
|
resize: function resize(width, height) {
|
||
|
if (map) {
|
||
|
map.invalidateSize();
|
||
|
|
||
|
if (map.leafletr.pendingRenderData) {
|
||
|
this.doRenderValue(map.leafletr.pendingRenderData, map);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (_htmlwidgets2["default"].shinyMode) {
|
||
|
_shiny2["default"].addCustomMessageHandler("leaflet-calls", function (data) {
|
||
|
var id = data.id;
|
||
|
var el = document.getElementById(id);
|
||
|
var map = el ? (0, _jquery2["default"])(el).data("leaflet-map") : null;
|
||
|
|
||
|
if (!map) {
|
||
|
(0, _util.log)("Couldn't find map with id " + id);
|
||
|
return;
|
||
|
} // If the map has not rendered, stash the proposed `leafletProxy()` calls
|
||
|
// in `pendingRenderData.calls` to be run on display via `doRenderValue()`.
|
||
|
// This is necessary if the map has not been rendered.
|
||
|
// If new pendingRenderData is set via a new `leaflet()`, the previous calls will be discarded.
|
||
|
|
||
|
|
||
|
if (!map.leafletr.hasRendered) {
|
||
|
map.leafletr.pendingRenderData.calls = map.leafletr.pendingRenderData.calls.concat(data.calls);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < data.calls.length; i++) {
|
||
|
var call = data.calls[i];
|
||
|
var args = call.args;
|
||
|
|
||
|
for (var _i = 0; _i < call.evals.length; _i++) {
|
||
|
window.HTMLWidgets.evaluateStringMember(args, call.evals[_i]);
|
||
|
}
|
||
|
|
||
|
if (call.dependencies) {
|
||
|
_shiny2["default"].renderDependencies(call.dependencies);
|
||
|
}
|
||
|
|
||
|
if (methods[call.method]) methods[call.method].apply(map, args);else (0, _util.log)("Unknown method " + call.method);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
|
||
|
},{"./cluster-layer-store":1,"./control-store":2,"./crs_utils":3,"./dataframe":4,"./fixup-default-icon":5,"./fixup-default-tooltip":6,"./fixup-url-protocol":7,"./global/htmlwidgets":8,"./global/jquery":9,"./global/leaflet":10,"./global/shiny":12,"./layer-manager":14,"./methods":15,"./util":17}],14:[function(require,module,exports){
|
||
|
(function (global){(function (){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports["default"] = undefined;
|
||
|
|
||
|
var _jquery = require("./global/jquery");
|
||
|
|
||
|
var _jquery2 = _interopRequireDefault(_jquery);
|
||
|
|
||
|
var _leaflet = require("./global/leaflet");
|
||
|
|
||
|
var _leaflet2 = _interopRequireDefault(_leaflet);
|
||
|
|
||
|
var _util = require("./util");
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||
|
|
||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
||
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||
|
|
||
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||
|
|
||
|
var LayerManager = /*#__PURE__*/function () {
|
||
|
function LayerManager(map) {
|
||
|
_classCallCheck(this, LayerManager);
|
||
|
|
||
|
this._map = map; // BEGIN layer indices
|
||
|
// {<groupname>: {<stamp>: layer}}
|
||
|
|
||
|
this._byGroup = {}; // {<categoryName>: {<stamp>: layer}}
|
||
|
|
||
|
this._byCategory = {}; // {<categoryName_layerId>: layer}
|
||
|
|
||
|
this._byLayerId = {}; // {<stamp>: {
|
||
|
// "group": <groupname>,
|
||
|
// "layerId": <layerId>,
|
||
|
// "category": <category>,
|
||
|
// "container": <container>
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
this._byStamp = {}; // {<crosstalkGroupName>: {<key>: [<stamp>, <stamp>, ...], ...}}
|
||
|
|
||
|
this._byCrosstalkGroup = {}; // END layer indices
|
||
|
// {<categoryName>: L.layerGroup}
|
||
|
|
||
|
this._categoryContainers = {}; // {<groupName>: L.layerGroup}
|
||
|
|
||
|
this._groupContainers = {};
|
||
|
}
|
||
|
|
||
|
_createClass(LayerManager, [{
|
||
|
key: "addLayer",
|
||
|
value: function addLayer(layer, category, layerId, group, ctGroup, ctKey) {
|
||
|
var _this = this;
|
||
|
|
||
|
// Was a group provided?
|
||
|
var hasId = typeof layerId === "string";
|
||
|
var grouped = typeof group === "string";
|
||
|
var stamp = _leaflet2["default"].Util.stamp(layer) + ""; // This will be the default layer group to add the layer to.
|
||
|
// We may overwrite this let before using it (i.e. if a group is assigned).
|
||
|
// This one liner creates the _categoryContainers[category] entry if it
|
||
|
// doesn't already exist.
|
||
|
|
||
|
var container = this._categoryContainers[category] = this._categoryContainers[category] || _leaflet2["default"].layerGroup().addTo(this._map);
|
||
|
|
||
|
var oldLayer = null;
|
||
|
|
||
|
if (hasId) {
|
||
|
// First, remove any layer with the same category and layerId
|
||
|
var prefixedLayerId = this._layerIdKey(category, layerId);
|
||
|
|
||
|
oldLayer = this._byLayerId[prefixedLayerId];
|
||
|
|
||
|
if (oldLayer) {
|
||
|
this._removeLayer(oldLayer);
|
||
|
} // Update layerId index
|
||
|
|
||
|
|
||
|
this._byLayerId[prefixedLayerId] = layer;
|
||
|
} // Update group index
|
||
|
|
||
|
|
||
|
if (grouped) {
|
||
|
this._byGroup[group] = this._byGroup[group] || {};
|
||
|
this._byGroup[group][stamp] = layer; // Since a group is assigned, don't add the layer to the category's layer
|
||
|
// group; instead, use the group's layer group.
|
||
|
// This one liner creates the _groupContainers[group] entry if it doesn't
|
||
|
// already exist.
|
||
|
|
||
|
container = this.getLayerGroup(group, true);
|
||
|
} // Update category index
|
||
|
|
||
|
|
||
|
this._byCategory[category] = this._byCategory[category] || {};
|
||
|
this._byCategory[category][stamp] = layer; // Update stamp index
|
||
|
|
||
|
var layerInfo = this._byStamp[stamp] = {
|
||
|
layer: layer,
|
||
|
group: group,
|
||
|
ctGroup: ctGroup,
|
||
|
ctKey: ctKey,
|
||
|
layerId: layerId,
|
||
|
category: category,
|
||
|
container: container,
|
||
|
hidden: false
|
||
|
}; // Update crosstalk group index
|
||
|
|
||
|
if (ctGroup) {
|
||
|
if (layer.setStyle) {
|
||
|
// Need to save this info so we know what to set opacity to later
|
||
|
layer.options.origOpacity = typeof layer.options.opacity !== "undefined" ? layer.options.opacity : 0.5;
|
||
|
layer.options.origFillOpacity = typeof layer.options.fillOpacity !== "undefined" ? layer.options.fillOpacity : 0.2;
|
||
|
}
|
||
|
|
||
|
var ctg = this._byCrosstalkGroup[ctGroup];
|
||
|
|
||
|
if (!ctg) {
|
||
|
ctg = this._byCrosstalkGroup[ctGroup] = {};
|
||
|
var crosstalk = global.crosstalk;
|
||
|
|
||
|
var handleFilter = function handleFilter(e) {
|
||
|
if (!e.value) {
|
||
|
var groupKeys = Object.keys(ctg);
|
||
|
|
||
|
for (var i = 0; i < groupKeys.length; i++) {
|
||
|
var key = groupKeys[i];
|
||
|
var _layerInfo = _this._byStamp[ctg[key]];
|
||
|
|
||
|
_this._setVisibility(_layerInfo, true);
|
||
|
}
|
||
|
} else {
|
||
|
var selectedKeys = {};
|
||
|
|
||
|
for (var _i = 0; _i < e.value.length; _i++) {
|
||
|
selectedKeys[e.value[_i]] = true;
|
||
|
}
|
||
|
|
||
|
var _groupKeys = Object.keys(ctg);
|
||
|
|
||
|
for (var _i2 = 0; _i2 < _groupKeys.length; _i2++) {
|
||
|
var _key = _groupKeys[_i2];
|
||
|
var _layerInfo2 = _this._byStamp[ctg[_key]];
|
||
|
|
||
|
_this._setVisibility(_layerInfo2, selectedKeys[_groupKeys[_i2]]);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var filterHandle = new crosstalk.FilterHandle(ctGroup);
|
||
|
filterHandle.on("change", handleFilter);
|
||
|
|
||
|
var handleSelection = function handleSelection(e) {
|
||
|
if (!e.value || !e.value.length) {
|
||
|
var groupKeys = Object.keys(ctg);
|
||
|
|
||
|
for (var i = 0; i < groupKeys.length; i++) {
|
||
|
var key = groupKeys[i];
|
||
|
var _layerInfo3 = _this._byStamp[ctg[key]];
|
||
|
|
||
|
_this._setOpacity(_layerInfo3, 1.0);
|
||
|
}
|
||
|
} else {
|
||
|
var selectedKeys = {};
|
||
|
|
||
|
for (var _i3 = 0; _i3 < e.value.length; _i3++) {
|
||
|
selectedKeys[e.value[_i3]] = true;
|
||
|
}
|
||
|
|
||
|
var _groupKeys2 = Object.keys(ctg);
|
||
|
|
||
|
for (var _i4 = 0; _i4 < _groupKeys2.length; _i4++) {
|
||
|
var _key2 = _groupKeys2[_i4];
|
||
|
var _layerInfo4 = _this._byStamp[ctg[_key2]];
|
||
|
|
||
|
_this._setOpacity(_layerInfo4, selectedKeys[_groupKeys2[_i4]] ? 1.0 : 0.2);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var selHandle = new crosstalk.SelectionHandle(ctGroup);
|
||
|
selHandle.on("change", handleSelection);
|
||
|
setTimeout(function () {
|
||
|
handleFilter({
|
||
|
value: filterHandle.filteredKeys
|
||
|
});
|
||
|
handleSelection({
|
||
|
value: selHandle.value
|
||
|
});
|
||
|
}, 100);
|
||
|
}
|
||
|
|
||
|
if (!ctg[ctKey]) ctg[ctKey] = [];
|
||
|
ctg[ctKey].push(stamp);
|
||
|
} // Add to container
|
||
|
|
||
|
|
||
|
if (!layerInfo.hidden) container.addLayer(layer);
|
||
|
return oldLayer;
|
||
|
}
|
||
|
}, {
|
||
|
key: "brush",
|
||
|
value: function brush(bounds, extraInfo) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
/* eslint-disable no-console */
|
||
|
// For each Crosstalk group...
|
||
|
Object.keys(this._byCrosstalkGroup).forEach(function (ctGroupName) {
|
||
|
var ctg = _this2._byCrosstalkGroup[ctGroupName];
|
||
|
var selection = []; // ...iterate over each Crosstalk key (each of which may have multiple
|
||
|
// layers)...
|
||
|
|
||
|
Object.keys(ctg).forEach(function (ctKey) {
|
||
|
// ...and for each layer...
|
||
|
ctg[ctKey].forEach(function (stamp) {
|
||
|
var layerInfo = _this2._byStamp[stamp]; // ...if it's something with a point...
|
||
|
|
||
|
if (layerInfo.layer.getLatLng) {
|
||
|
// ... and it's inside the selection bounds...
|
||
|
// TODO: Use pixel containment, not lat/lng containment
|
||
|
if (bounds.contains(layerInfo.layer.getLatLng())) {
|
||
|
// ...add the key to the selection.
|
||
|
selection.push(ctKey);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
new global.crosstalk.SelectionHandle(ctGroupName).set(selection, extraInfo);
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: "unbrush",
|
||
|
value: function unbrush(extraInfo) {
|
||
|
Object.keys(this._byCrosstalkGroup).forEach(function (ctGroupName) {
|
||
|
new global.crosstalk.SelectionHandle(ctGroupName).clear(extraInfo);
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: "_setVisibility",
|
||
|
value: function _setVisibility(layerInfo, visible) {
|
||
|
if (layerInfo.hidden ^ visible) {
|
||
|
return;
|
||
|
} else if (visible) {
|
||
|
layerInfo.container.addLayer(layerInfo.layer);
|
||
|
layerInfo.hidden = false;
|
||
|
} else {
|
||
|
layerInfo.container.removeLayer(layerInfo.layer);
|
||
|
layerInfo.hidden = true;
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: "_setOpacity",
|
||
|
value: function _setOpacity(layerInfo, opacity) {
|
||
|
if (layerInfo.layer.setOpacity) {
|
||
|
layerInfo.layer.setOpacity(opacity);
|
||
|
} else if (layerInfo.layer.setStyle) {
|
||
|
layerInfo.layer.setStyle({
|
||
|
opacity: opacity * layerInfo.layer.options.origOpacity,
|
||
|
fillOpacity: opacity * layerInfo.layer.options.origFillOpacity
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: "getLayer",
|
||
|
value: function getLayer(category, layerId) {
|
||
|
return this._byLayerId[this._layerIdKey(category, layerId)];
|
||
|
}
|
||
|
}, {
|
||
|
key: "removeLayer",
|
||
|
value: function removeLayer(category, layerIds) {
|
||
|
var _this3 = this;
|
||
|
|
||
|
// Find layer info
|
||
|
_jquery2["default"].each((0, _util.asArray)(layerIds), function (i, layerId) {
|
||
|
var layer = _this3._byLayerId[_this3._layerIdKey(category, layerId)];
|
||
|
|
||
|
if (layer) {
|
||
|
_this3._removeLayer(layer);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: "clearLayers",
|
||
|
value: function clearLayers(category) {
|
||
|
var _this4 = this;
|
||
|
|
||
|
// Find all layers in _byCategory[category]
|
||
|
var catTable = this._byCategory[category];
|
||
|
|
||
|
if (!catTable) {
|
||
|
return false;
|
||
|
} // Remove all layers. Make copy of keys to avoid mutating the collection
|
||
|
// behind the iterator you're accessing.
|
||
|
|
||
|
|
||
|
var stamps = [];
|
||
|
|
||
|
_jquery2["default"].each(catTable, function (k, v) {
|
||
|
stamps.push(k);
|
||
|
});
|
||
|
|
||
|
_jquery2["default"].each(stamps, function (i, stamp) {
|
||
|
_this4._removeLayer(stamp);
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: "getLayerGroup",
|
||
|
value: function getLayerGroup(group, ensureExists) {
|
||
|
var g = this._groupContainers[group];
|
||
|
|
||
|
if (ensureExists && !g) {
|
||
|
this._byGroup[group] = this._byGroup[group] || {};
|
||
|
g = this._groupContainers[group] = _leaflet2["default"].featureGroup();
|
||
|
g.groupname = group;
|
||
|
g.addTo(this._map);
|
||
|
}
|
||
|
|
||
|
return g;
|
||
|
}
|
||
|
}, {
|
||
|
key: "getGroupNameFromLayerGroup",
|
||
|
value: function getGroupNameFromLayerGroup(layerGroup) {
|
||
|
return layerGroup.groupname;
|
||
|
}
|
||
|
}, {
|
||
|
key: "getVisibleGroups",
|
||
|
value: function getVisibleGroups() {
|
||
|
var _this5 = this;
|
||
|
|
||
|
var result = [];
|
||
|
|
||
|
_jquery2["default"].each(this._groupContainers, function (k, v) {
|
||
|
if (_this5._map.hasLayer(v)) {
|
||
|
result.push(k);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
}, {
|
||
|
key: "getAllGroupNames",
|
||
|
value: function getAllGroupNames() {
|
||
|
var result = [];
|
||
|
|
||
|
_jquery2["default"].each(this._groupContainers, function (k, v) {
|
||
|
result.push(k);
|
||
|
});
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
}, {
|
||
|
key: "clearGroup",
|
||
|
value: function clearGroup(group) {
|
||
|
var _this6 = this;
|
||
|
|
||
|
// Find all layers in _byGroup[group]
|
||
|
var groupTable = this._byGroup[group];
|
||
|
|
||
|
if (!groupTable) {
|
||
|
return false;
|
||
|
} // Remove all layers. Make copy of keys to avoid mutating the collection
|
||
|
// behind the iterator you're accessing.
|
||
|
|
||
|
|
||
|
var stamps = [];
|
||
|
|
||
|
_jquery2["default"].each(groupTable, function (k, v) {
|
||
|
stamps.push(k);
|
||
|
});
|
||
|
|
||
|
_jquery2["default"].each(stamps, function (i, stamp) {
|
||
|
_this6._removeLayer(stamp);
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: "clear",
|
||
|
value: function clear() {
|
||
|
function clearLayerGroup(key, layerGroup) {
|
||
|
layerGroup.clearLayers();
|
||
|
} // Clear all indices and layerGroups
|
||
|
|
||
|
|
||
|
this._byGroup = {};
|
||
|
this._byCategory = {};
|
||
|
this._byLayerId = {};
|
||
|
this._byStamp = {};
|
||
|
this._byCrosstalkGroup = {};
|
||
|
|
||
|
_jquery2["default"].each(this._categoryContainers, clearLayerGroup);
|
||
|
|
||
|
this._categoryContainers = {};
|
||
|
|
||
|
_jquery2["default"].each(this._groupContainers, clearLayerGroup);
|
||
|
|
||
|
this._groupContainers = {};
|
||
|
}
|
||
|
}, {
|
||
|
key: "_removeLayer",
|
||
|
value: function _removeLayer(layer) {
|
||
|
var stamp;
|
||
|
|
||
|
if (typeof layer === "string") {
|
||
|
stamp = layer;
|
||
|
} else {
|
||
|
stamp = _leaflet2["default"].Util.stamp(layer);
|
||
|
}
|
||
|
|
||
|
var layerInfo = this._byStamp[stamp];
|
||
|
|
||
|
if (!layerInfo) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
layerInfo.container.removeLayer(stamp);
|
||
|
|
||
|
if (typeof layerInfo.group === "string") {
|
||
|
delete this._byGroup[layerInfo.group][stamp];
|
||
|
}
|
||
|
|
||
|
if (typeof layerInfo.layerId === "string") {
|
||
|
delete this._byLayerId[this._layerIdKey(layerInfo.category, layerInfo.layerId)];
|
||
|
}
|
||
|
|
||
|
delete this._byCategory[layerInfo.category][stamp];
|
||
|
delete this._byStamp[stamp];
|
||
|
|
||
|
if (layerInfo.ctGroup) {
|
||
|
var ctGroup = this._byCrosstalkGroup[layerInfo.ctGroup];
|
||
|
var layersForKey = ctGroup[layerInfo.ctKey];
|
||
|
var idx = layersForKey ? layersForKey.indexOf(stamp) : -1;
|
||
|
|
||
|
if (idx >= 0) {
|
||
|
if (layersForKey.length === 1) {
|
||
|
delete ctGroup[layerInfo.ctKey];
|
||
|
} else {
|
||
|
layersForKey.splice(idx, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: "_layerIdKey",
|
||
|
value: function _layerIdKey(category, layerId) {
|
||
|
return category + "\n" + layerId;
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return LayerManager;
|
||
|
}();
|
||
|
|
||
|
exports["default"] = LayerManager;
|
||
|
|
||
|
|
||
|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
|
},{"./global/jquery":9,"./global/leaflet":10,"./util":17}],15:[function(require,module,exports){
|
||
|
(function (global){(function (){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
|
||
|
var _jquery = require("./global/jquery");
|
||
|
|
||
|
var _jquery2 = _interopRequireDefault(_jquery);
|
||
|
|
||
|
var _leaflet = require("./global/leaflet");
|
||
|
|
||
|
var _leaflet2 = _interopRequireDefault(_leaflet);
|
||
|
|
||
|
var _shiny = require("./global/shiny");
|
||
|
|
||
|
var _shiny2 = _interopRequireDefault(_shiny);
|
||
|
|
||
|
var _htmlwidgets = require("./global/htmlwidgets");
|
||
|
|
||
|
var _htmlwidgets2 = _interopRequireDefault(_htmlwidgets);
|
||
|
|
||
|
var _util = require("./util");
|
||
|
|
||
|
var _crs_utils = require("./crs_utils");
|
||
|
|
||
|
var _dataframe = require("./dataframe");
|
||
|
|
||
|
var _dataframe2 = _interopRequireDefault(_dataframe);
|
||
|
|
||
|
var _clusterLayerStore = require("./cluster-layer-store");
|
||
|
|
||
|
var _clusterLayerStore2 = _interopRequireDefault(_clusterLayerStore);
|
||
|
|
||
|
var _mipmapper = require("./mipmapper");
|
||
|
|
||
|
var _mipmapper2 = _interopRequireDefault(_mipmapper);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
||
|
|
||
|
var methods = {};
|
||
|
exports["default"] = methods;
|
||
|
|
||
|
function mouseHandler(mapId, layerId, group, eventName, extraInfo) {
|
||
|
return function (e) {
|
||
|
if (!_htmlwidgets2["default"].shinyMode) return;
|
||
|
var latLng = e.target.getLatLng ? e.target.getLatLng() : e.latlng;
|
||
|
|
||
|
if (latLng) {
|
||
|
// retrieve only lat, lon values to remove prototype
|
||
|
// and extra parameters added by 3rd party modules
|
||
|
// these objects are for json serialization, not javascript
|
||
|
var latLngVal = _leaflet2["default"].latLng(latLng); // make sure it has consistent shape
|
||
|
|
||
|
|
||
|
latLng = {
|
||
|
lat: latLngVal.lat,
|
||
|
lng: latLngVal.lng
|
||
|
};
|
||
|
}
|
||
|
|
||
|
var eventInfo = _jquery2["default"].extend({
|
||
|
id: layerId,
|
||
|
".nonce": Math.random() // force reactivity
|
||
|
|
||
|
}, group !== null ? {
|
||
|
group: group
|
||
|
} : null, latLng, extraInfo);
|
||
|
|
||
|
_shiny2["default"].onInputChange(mapId + "_" + eventName, eventInfo);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
methods.mouseHandler = mouseHandler;
|
||
|
|
||
|
methods.clearGroup = function (group) {
|
||
|
var _this = this;
|
||
|
|
||
|
_jquery2["default"].each((0, _util.asArray)(group), function (i, v) {
|
||
|
_this.layerManager.clearGroup(v);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
methods.setView = function (center, zoom, options) {
|
||
|
this.setView(center, zoom, options);
|
||
|
};
|
||
|
|
||
|
methods.fitBounds = function (lat1, lng1, lat2, lng2, options) {
|
||
|
this.fitBounds([[lat1, lng1], [lat2, lng2]], options);
|
||
|
};
|
||
|
|
||
|
methods.flyTo = function (center, zoom, options) {
|
||
|
this.flyTo(center, zoom, options);
|
||
|
};
|
||
|
|
||
|
methods.flyToBounds = function (lat1, lng1, lat2, lng2, options) {
|
||
|
this.flyToBounds([[lat1, lng1], [lat2, lng2]], options);
|
||
|
};
|
||
|
|
||
|
methods.setMaxBounds = function (lat1, lng1, lat2, lng2) {
|
||
|
this.setMaxBounds([[lat1, lng1], [lat2, lng2]]);
|
||
|
};
|
||
|
|
||
|
methods.addPopups = function (lat, lng, popup, layerId, group, options) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("popup", popup).col("layerId", layerId).col("group", group).cbind(options);
|
||
|
|
||
|
var _loop = function _loop(i) {
|
||
|
if (_jquery2["default"].isNumeric(df.get(i, "lat")) && _jquery2["default"].isNumeric(df.get(i, "lng"))) {
|
||
|
(function () {
|
||
|
var popup = _leaflet2["default"].popup(df.get(i)).setLatLng([df.get(i, "lat"), df.get(i, "lng")]).setContent(df.get(i, "popup"));
|
||
|
|
||
|
var thisId = df.get(i, "layerId");
|
||
|
var thisGroup = df.get(i, "group");
|
||
|
this.layerManager.addLayer(popup, "popup", thisId, thisGroup);
|
||
|
}).call(_this2);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
for (var i = 0; i < df.nrow(); i++) {
|
||
|
_loop(i);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.removePopup = function (layerId) {
|
||
|
this.layerManager.removeLayer("popup", layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearPopups = function () {
|
||
|
this.layerManager.clearLayers("popup");
|
||
|
};
|
||
|
|
||
|
methods.addTiles = function (urlTemplate, layerId, group, options) {
|
||
|
this.layerManager.addLayer(_leaflet2["default"].tileLayer(urlTemplate, options), "tile", layerId, group);
|
||
|
};
|
||
|
|
||
|
methods.removeTiles = function (layerId) {
|
||
|
this.layerManager.removeLayer("tile", layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearTiles = function () {
|
||
|
this.layerManager.clearLayers("tile");
|
||
|
};
|
||
|
|
||
|
methods.addWMSTiles = function (baseUrl, layerId, group, options) {
|
||
|
if (options && options.crs) {
|
||
|
options.crs = (0, _crs_utils.getCRS)(options.crs);
|
||
|
}
|
||
|
|
||
|
this.layerManager.addLayer(_leaflet2["default"].tileLayer.wms(baseUrl, options), "tile", layerId, group);
|
||
|
}; // Given:
|
||
|
// {data: ["a", "b", "c"], index: [0, 1, 0, 2]}
|
||
|
// returns:
|
||
|
// ["a", "b", "a", "c"]
|
||
|
|
||
|
|
||
|
function unpackStrings(iconset) {
|
||
|
if (!iconset) {
|
||
|
return iconset;
|
||
|
}
|
||
|
|
||
|
if (typeof iconset.index === "undefined") {
|
||
|
return iconset;
|
||
|
}
|
||
|
|
||
|
iconset.data = (0, _util.asArray)(iconset.data);
|
||
|
iconset.index = (0, _util.asArray)(iconset.index);
|
||
|
return _jquery2["default"].map(iconset.index, function (e, i) {
|
||
|
return iconset.data[e];
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function addMarkers(map, df, group, clusterOptions, clusterId, markerFunc) {
|
||
|
(function () {
|
||
|
var _this3 = this;
|
||
|
|
||
|
var clusterGroup = this.layerManager.getLayer("cluster", clusterId),
|
||
|
cluster = clusterOptions !== null;
|
||
|
|
||
|
if (cluster && !clusterGroup) {
|
||
|
clusterGroup = _leaflet2["default"].markerClusterGroup.layerSupport(clusterOptions);
|
||
|
|
||
|
if (clusterOptions.freezeAtZoom) {
|
||
|
var freezeAtZoom = clusterOptions.freezeAtZoom;
|
||
|
delete clusterOptions.freezeAtZoom;
|
||
|
clusterGroup.freezeAtZoom(freezeAtZoom);
|
||
|
}
|
||
|
|
||
|
clusterGroup.clusterLayerStore = new _clusterLayerStore2["default"](clusterGroup);
|
||
|
}
|
||
|
|
||
|
var extraInfo = cluster ? {
|
||
|
clusterId: clusterId
|
||
|
} : {};
|
||
|
|
||
|
var _loop2 = function _loop2(i) {
|
||
|
if (_jquery2["default"].isNumeric(df.get(i, "lat")) && _jquery2["default"].isNumeric(df.get(i, "lng"))) {
|
||
|
(function () {
|
||
|
var marker = markerFunc(df, i);
|
||
|
var thisId = df.get(i, "layerId");
|
||
|
var thisGroup = cluster ? null : df.get(i, "group");
|
||
|
|
||
|
if (cluster) {
|
||
|
clusterGroup.clusterLayerStore.add(marker, thisId);
|
||
|
} else {
|
||
|
this.layerManager.addLayer(marker, "marker", thisId, thisGroup, df.get(i, "ctGroup", true), df.get(i, "ctKey", true));
|
||
|
}
|
||
|
|
||
|
var popup = df.get(i, "popup");
|
||
|
var popupOptions = df.get(i, "popupOptions");
|
||
|
|
||
|
if (popup !== null) {
|
||
|
if (popupOptions !== null) {
|
||
|
marker.bindPopup(popup, popupOptions);
|
||
|
} else {
|
||
|
marker.bindPopup(popup);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var label = df.get(i, "label");
|
||
|
var labelOptions = df.get(i, "labelOptions");
|
||
|
|
||
|
if (label !== null) {
|
||
|
if (labelOptions !== null) {
|
||
|
if (labelOptions.permanent) {
|
||
|
marker.bindTooltip(label, labelOptions).openTooltip();
|
||
|
} else {
|
||
|
marker.bindTooltip(label, labelOptions);
|
||
|
}
|
||
|
} else {
|
||
|
marker.bindTooltip(label);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
marker.on("click", mouseHandler(this.id, thisId, thisGroup, "marker_click", extraInfo), this);
|
||
|
marker.on("mouseover", mouseHandler(this.id, thisId, thisGroup, "marker_mouseover", extraInfo), this);
|
||
|
marker.on("mouseout", mouseHandler(this.id, thisId, thisGroup, "marker_mouseout", extraInfo), this);
|
||
|
marker.on("dragend", mouseHandler(this.id, thisId, thisGroup, "marker_dragend", extraInfo), this);
|
||
|
}).call(_this3);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
for (var i = 0; i < df.nrow(); i++) {
|
||
|
_loop2(i);
|
||
|
}
|
||
|
|
||
|
if (cluster) {
|
||
|
this.layerManager.addLayer(clusterGroup, "cluster", clusterId, group);
|
||
|
}
|
||
|
}).call(map);
|
||
|
}
|
||
|
|
||
|
methods.addGenericMarkers = addMarkers;
|
||
|
|
||
|
methods.addMarkers = function (lat, lng, icon, layerId, group, options, popup, popupOptions, clusterOptions, clusterId, label, labelOptions, crosstalkOptions) {
|
||
|
var icondf;
|
||
|
var getIcon;
|
||
|
|
||
|
if (icon) {
|
||
|
// Unpack icons
|
||
|
icon.iconUrl = unpackStrings(icon.iconUrl);
|
||
|
icon.iconRetinaUrl = unpackStrings(icon.iconRetinaUrl);
|
||
|
icon.shadowUrl = unpackStrings(icon.shadowUrl);
|
||
|
icon.shadowRetinaUrl = unpackStrings(icon.shadowRetinaUrl); // This cbinds the icon URLs and any other icon options; they're all
|
||
|
// present on the icon object.
|
||
|
|
||
|
icondf = new _dataframe2["default"]().cbind(icon); // Constructs an icon from a specified row of the icon dataframe.
|
||
|
|
||
|
getIcon = function getIcon(i) {
|
||
|
var opts = icondf.get(i);
|
||
|
|
||
|
if (!opts.iconUrl) {
|
||
|
return new _leaflet2["default"].Icon.Default();
|
||
|
} // Composite options (like points or sizes) are passed from R with each
|
||
|
// individual component as its own option. We need to combine them now
|
||
|
// into their composite form.
|
||
|
|
||
|
|
||
|
if (opts.iconWidth) {
|
||
|
opts.iconSize = [opts.iconWidth, opts.iconHeight];
|
||
|
}
|
||
|
|
||
|
if (opts.shadowWidth) {
|
||
|
opts.shadowSize = [opts.shadowWidth, opts.shadowHeight];
|
||
|
}
|
||
|
|
||
|
if (opts.iconAnchorX) {
|
||
|
opts.iconAnchor = [opts.iconAnchorX, opts.iconAnchorY];
|
||
|
}
|
||
|
|
||
|
if (opts.shadowAnchorX) {
|
||
|
opts.shadowAnchor = [opts.shadowAnchorX, opts.shadowAnchorY];
|
||
|
}
|
||
|
|
||
|
if (opts.popupAnchorX) {
|
||
|
opts.popupAnchor = [opts.popupAnchorX, opts.popupAnchorY];
|
||
|
}
|
||
|
|
||
|
return new _leaflet2["default"].Icon(opts);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) {
|
||
|
var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).cbind(options).cbind(crosstalkOptions || {});
|
||
|
if (icon) icondf.effectiveLength = df.nrow();
|
||
|
addMarkers(this, df, group, clusterOptions, clusterId, function (df, i) {
|
||
|
var options = df.get(i);
|
||
|
if (icon) options.icon = getIcon(i);
|
||
|
return _leaflet2["default"].marker([df.get(i, "lat"), df.get(i, "lng")], options);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.addAwesomeMarkers = function (lat, lng, icon, layerId, group, options, popup, popupOptions, clusterOptions, clusterId, label, labelOptions, crosstalkOptions) {
|
||
|
var icondf;
|
||
|
var getIcon;
|
||
|
|
||
|
if (icon) {
|
||
|
// This cbinds the icon URLs and any other icon options; they're all
|
||
|
// present on the icon object.
|
||
|
icondf = new _dataframe2["default"]().cbind(icon); // Constructs an icon from a specified row of the icon dataframe.
|
||
|
|
||
|
getIcon = function getIcon(i) {
|
||
|
var opts = icondf.get(i);
|
||
|
|
||
|
if (!opts) {
|
||
|
return new _leaflet2["default"].AwesomeMarkers.icon();
|
||
|
}
|
||
|
|
||
|
if (opts.squareMarker) {
|
||
|
opts.className = "awesome-marker awesome-marker-square";
|
||
|
}
|
||
|
|
||
|
return new _leaflet2["default"].AwesomeMarkers.icon(opts);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) {
|
||
|
var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).cbind(options).cbind(crosstalkOptions || {});
|
||
|
if (icon) icondf.effectiveLength = df.nrow();
|
||
|
addMarkers(this, df, group, clusterOptions, clusterId, function (df, i) {
|
||
|
var options = df.get(i);
|
||
|
if (icon) options.icon = getIcon(i);
|
||
|
return _leaflet2["default"].marker([df.get(i, "lat"), df.get(i, "lng")], options);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
function addLayers(map, category, df, layerFunc) {
|
||
|
var _loop3 = function _loop3(i) {
|
||
|
(function () {
|
||
|
var layer = layerFunc(df, i);
|
||
|
|
||
|
if (!_jquery2["default"].isEmptyObject(layer)) {
|
||
|
var thisId = df.get(i, "layerId");
|
||
|
var thisGroup = df.get(i, "group");
|
||
|
this.layerManager.addLayer(layer, category, thisId, thisGroup, df.get(i, "ctGroup", true), df.get(i, "ctKey", true));
|
||
|
|
||
|
if (layer.bindPopup) {
|
||
|
var popup = df.get(i, "popup");
|
||
|
var popupOptions = df.get(i, "popupOptions");
|
||
|
|
||
|
if (popup !== null) {
|
||
|
if (popupOptions !== null) {
|
||
|
layer.bindPopup(popup, popupOptions);
|
||
|
} else {
|
||
|
layer.bindPopup(popup);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (layer.bindTooltip) {
|
||
|
var label = df.get(i, "label");
|
||
|
var labelOptions = df.get(i, "labelOptions");
|
||
|
|
||
|
if (label !== null) {
|
||
|
if (labelOptions !== null) {
|
||
|
layer.bindTooltip(label, labelOptions);
|
||
|
} else {
|
||
|
layer.bindTooltip(label);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
layer.on("click", mouseHandler(this.id, thisId, thisGroup, category + "_click"), this);
|
||
|
layer.on("mouseover", mouseHandler(this.id, thisId, thisGroup, category + "_mouseover"), this);
|
||
|
layer.on("mouseout", mouseHandler(this.id, thisId, thisGroup, category + "_mouseout"), this);
|
||
|
var highlightStyle = df.get(i, "highlightOptions");
|
||
|
|
||
|
if (!_jquery2["default"].isEmptyObject(highlightStyle)) {
|
||
|
var defaultStyle = {};
|
||
|
|
||
|
_jquery2["default"].each(highlightStyle, function (k, v) {
|
||
|
if (k != "bringToFront" && k != "sendToBack") {
|
||
|
if (df.get(i, k)) {
|
||
|
defaultStyle[k] = df.get(i, k);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
layer.on("mouseover", function (e) {
|
||
|
this.setStyle(highlightStyle);
|
||
|
|
||
|
if (highlightStyle.bringToFront) {
|
||
|
this.bringToFront();
|
||
|
}
|
||
|
});
|
||
|
layer.on("mouseout", function (e) {
|
||
|
this.setStyle(defaultStyle);
|
||
|
|
||
|
if (highlightStyle.sendToBack) {
|
||
|
this.bringToBack();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}).call(map);
|
||
|
};
|
||
|
|
||
|
for (var i = 0; i < df.nrow(); i++) {
|
||
|
_loop3(i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
methods.addGenericLayers = addLayers;
|
||
|
|
||
|
methods.addCircles = function (lat, lng, radius, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions, crosstalkOptions) {
|
||
|
if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) {
|
||
|
var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("radius", radius).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options).cbind(crosstalkOptions || {});
|
||
|
addLayers(this, "shape", df, function (df, i) {
|
||
|
if (_jquery2["default"].isNumeric(df.get(i, "lat")) && _jquery2["default"].isNumeric(df.get(i, "lng")) && _jquery2["default"].isNumeric(df.get(i, "radius"))) {
|
||
|
return _leaflet2["default"].circle([df.get(i, "lat"), df.get(i, "lng")], df.get(i, "radius"), df.get(i));
|
||
|
} else {
|
||
|
return null;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.addCircleMarkers = function (lat, lng, radius, layerId, group, options, clusterOptions, clusterId, popup, popupOptions, label, labelOptions, crosstalkOptions) {
|
||
|
if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) {
|
||
|
var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("radius", radius).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).cbind(crosstalkOptions || {}).cbind(options);
|
||
|
addMarkers(this, df, group, clusterOptions, clusterId, function (df, i) {
|
||
|
return _leaflet2["default"].circleMarker([df.get(i, "lat"), df.get(i, "lng")], df.get(i));
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
/*
|
||
|
* @param lat Array of arrays of latitude coordinates for polylines
|
||
|
* @param lng Array of arrays of longitude coordinates for polylines
|
||
|
*/
|
||
|
|
||
|
|
||
|
methods.addPolylines = function (polygons, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions) {
|
||
|
if (polygons.length > 0) {
|
||
|
var df = new _dataframe2["default"]().col("shapes", polygons).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options);
|
||
|
addLayers(this, "shape", df, function (df, i) {
|
||
|
var shapes = df.get(i, "shapes");
|
||
|
shapes = shapes.map(function (shape) {
|
||
|
return _htmlwidgets2["default"].dataframeToD3(shape[0]);
|
||
|
});
|
||
|
|
||
|
if (shapes.length > 1) {
|
||
|
return _leaflet2["default"].polyline(shapes, df.get(i));
|
||
|
} else {
|
||
|
return _leaflet2["default"].polyline(shapes[0], df.get(i));
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.removeMarker = function (layerId) {
|
||
|
this.layerManager.removeLayer("marker", layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearMarkers = function () {
|
||
|
this.layerManager.clearLayers("marker");
|
||
|
};
|
||
|
|
||
|
methods.removeMarkerCluster = function (layerId) {
|
||
|
this.layerManager.removeLayer("cluster", layerId);
|
||
|
};
|
||
|
|
||
|
methods.removeMarkerFromCluster = function (layerId, clusterId) {
|
||
|
var cluster = this.layerManager.getLayer("cluster", clusterId);
|
||
|
if (!cluster) return;
|
||
|
cluster.clusterLayerStore.remove(layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearMarkerClusters = function () {
|
||
|
this.layerManager.clearLayers("cluster");
|
||
|
};
|
||
|
|
||
|
methods.removeShape = function (layerId) {
|
||
|
this.layerManager.removeLayer("shape", layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearShapes = function () {
|
||
|
this.layerManager.clearLayers("shape");
|
||
|
};
|
||
|
|
||
|
methods.addRectangles = function (lat1, lng1, lat2, lng2, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions) {
|
||
|
var df = new _dataframe2["default"]().col("lat1", lat1).col("lng1", lng1).col("lat2", lat2).col("lng2", lng2).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options);
|
||
|
addLayers(this, "shape", df, function (df, i) {
|
||
|
if (_jquery2["default"].isNumeric(df.get(i, "lat1")) && _jquery2["default"].isNumeric(df.get(i, "lng1")) && _jquery2["default"].isNumeric(df.get(i, "lat2")) && _jquery2["default"].isNumeric(df.get(i, "lng2"))) {
|
||
|
return _leaflet2["default"].rectangle([[df.get(i, "lat1"), df.get(i, "lng1")], [df.get(i, "lat2"), df.get(i, "lng2")]], df.get(i));
|
||
|
} else {
|
||
|
return null;
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
/*
|
||
|
* @param lat Array of arrays of latitude coordinates for polygons
|
||
|
* @param lng Array of arrays of longitude coordinates for polygons
|
||
|
*/
|
||
|
|
||
|
|
||
|
methods.addPolygons = function (polygons, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions) {
|
||
|
if (polygons.length > 0) {
|
||
|
var df = new _dataframe2["default"]().col("shapes", polygons).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options);
|
||
|
addLayers(this, "shape", df, function (df, i) {
|
||
|
// This code used to use L.multiPolygon, but that caused
|
||
|
// double-click on a multipolygon to fail to zoom in on the
|
||
|
// map. Surprisingly, putting all the rings in a single
|
||
|
// polygon seems to still work; complicated multipolygons
|
||
|
// are still rendered correctly.
|
||
|
var shapes = df.get(i, "shapes").map(function (polygon) {
|
||
|
return polygon.map(_htmlwidgets2["default"].dataframeToD3);
|
||
|
}).reduce(function (acc, val) {
|
||
|
return acc.concat(val);
|
||
|
}, []);
|
||
|
return _leaflet2["default"].polygon(shapes, df.get(i));
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.addGeoJSON = function (data, layerId, group, style) {
|
||
|
// This time, self is actually needed because the callbacks below need
|
||
|
// to access both the inner and outer senses of "this"
|
||
|
var self = this;
|
||
|
|
||
|
if (typeof data === "string") {
|
||
|
data = JSON.parse(data);
|
||
|
}
|
||
|
|
||
|
var globalStyle = _jquery2["default"].extend({}, style, data.style || {});
|
||
|
|
||
|
var gjlayer = _leaflet2["default"].geoJson(data, {
|
||
|
style: function style(feature) {
|
||
|
if (feature.style || feature.properties.style) {
|
||
|
return _jquery2["default"].extend({}, globalStyle, feature.style, feature.properties.style);
|
||
|
} else {
|
||
|
return globalStyle;
|
||
|
}
|
||
|
},
|
||
|
onEachFeature: function onEachFeature(feature, layer) {
|
||
|
var extraInfo = {
|
||
|
featureId: feature.id,
|
||
|
properties: feature.properties
|
||
|
};
|
||
|
var popup = feature.properties ? feature.properties.popup : null;
|
||
|
if (typeof popup !== "undefined" && popup !== null) layer.bindPopup(popup);
|
||
|
layer.on("click", mouseHandler(self.id, layerId, group, "geojson_click", extraInfo), this);
|
||
|
layer.on("mouseover", mouseHandler(self.id, layerId, group, "geojson_mouseover", extraInfo), this);
|
||
|
layer.on("mouseout", mouseHandler(self.id, layerId, group, "geojson_mouseout", extraInfo), this);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
this.layerManager.addLayer(gjlayer, "geojson", layerId, group);
|
||
|
};
|
||
|
|
||
|
methods.removeGeoJSON = function (layerId) {
|
||
|
this.layerManager.removeLayer("geojson", layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearGeoJSON = function () {
|
||
|
this.layerManager.clearLayers("geojson");
|
||
|
};
|
||
|
|
||
|
methods.addTopoJSON = function (data, layerId, group, style) {
|
||
|
// This time, self is actually needed because the callbacks below need
|
||
|
// to access both the inner and outer senses of "this"
|
||
|
var self = this;
|
||
|
|
||
|
if (typeof data === "string") {
|
||
|
data = JSON.parse(data);
|
||
|
}
|
||
|
|
||
|
var globalStyle = _jquery2["default"].extend({}, style, data.style || {});
|
||
|
|
||
|
var gjlayer = _leaflet2["default"].geoJson(null, {
|
||
|
style: function style(feature) {
|
||
|
if (feature.style || feature.properties.style) {
|
||
|
return _jquery2["default"].extend({}, globalStyle, feature.style, feature.properties.style);
|
||
|
} else {
|
||
|
return globalStyle;
|
||
|
}
|
||
|
},
|
||
|
onEachFeature: function onEachFeature(feature, layer) {
|
||
|
var extraInfo = {
|
||
|
featureId: feature.id,
|
||
|
properties: feature.properties
|
||
|
};
|
||
|
var popup = feature.properties.popup;
|
||
|
if (typeof popup !== "undefined" && popup !== null) layer.bindPopup(popup);
|
||
|
layer.on("click", mouseHandler(self.id, layerId, group, "topojson_click", extraInfo), this);
|
||
|
layer.on("mouseover", mouseHandler(self.id, layerId, group, "topojson_mouseover", extraInfo), this);
|
||
|
layer.on("mouseout", mouseHandler(self.id, layerId, group, "topojson_mouseout", extraInfo), this);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
global.omnivore.topojson.parse(data, null, gjlayer);
|
||
|
this.layerManager.addLayer(gjlayer, "topojson", layerId, group);
|
||
|
};
|
||
|
|
||
|
methods.removeTopoJSON = function (layerId) {
|
||
|
this.layerManager.removeLayer("topojson", layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearTopoJSON = function () {
|
||
|
this.layerManager.clearLayers("topojson");
|
||
|
};
|
||
|
|
||
|
methods.addControl = function (html, position, layerId, classes) {
|
||
|
function onAdd(map) {
|
||
|
var div = _leaflet2["default"].DomUtil.create("div", classes);
|
||
|
|
||
|
if (typeof layerId !== "undefined" && layerId !== null) {
|
||
|
div.setAttribute("id", layerId);
|
||
|
}
|
||
|
|
||
|
this._div = div; // It's possible for window.Shiny to be true but Shiny.initializeInputs to
|
||
|
// not be, when a static leaflet widget is included as part of the shiny
|
||
|
// UI directly (not through leafletOutput or uiOutput). In this case we
|
||
|
// don't do the normal Shiny stuff as that will all happen when Shiny
|
||
|
// itself loads and binds the entire doc.
|
||
|
|
||
|
if (window.Shiny && _shiny2["default"].initializeInputs) {
|
||
|
_shiny2["default"].renderHtml(html, this._div);
|
||
|
|
||
|
_shiny2["default"].initializeInputs(this._div);
|
||
|
|
||
|
_shiny2["default"].bindAll(this._div);
|
||
|
} else {
|
||
|
this._div.innerHTML = html;
|
||
|
}
|
||
|
|
||
|
return this._div;
|
||
|
}
|
||
|
|
||
|
function onRemove(map) {
|
||
|
if (window.Shiny && _shiny2["default"].unbindAll) {
|
||
|
_shiny2["default"].unbindAll(this._div);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var Control = _leaflet2["default"].Control.extend({
|
||
|
options: {
|
||
|
position: position
|
||
|
},
|
||
|
onAdd: onAdd,
|
||
|
onRemove: onRemove
|
||
|
});
|
||
|
|
||
|
this.controls.add(new Control(), layerId, html);
|
||
|
};
|
||
|
|
||
|
methods.addCustomControl = function (control, layerId) {
|
||
|
this.controls.add(control, layerId);
|
||
|
};
|
||
|
|
||
|
methods.removeControl = function (layerId) {
|
||
|
this.controls.remove(layerId);
|
||
|
};
|
||
|
|
||
|
methods.getControl = function (layerId) {
|
||
|
this.controls.get(layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearControls = function () {
|
||
|
this.controls.clear();
|
||
|
};
|
||
|
|
||
|
methods.addLegend = function (options) {
|
||
|
var legend = _leaflet2["default"].control({
|
||
|
position: options.position
|
||
|
});
|
||
|
|
||
|
var gradSpan;
|
||
|
|
||
|
legend.onAdd = function (map) {
|
||
|
var div = _leaflet2["default"].DomUtil.create("div", options.className),
|
||
|
colors = options.colors,
|
||
|
labels = options.labels,
|
||
|
legendHTML = "";
|
||
|
|
||
|
if (options.type === "numeric") {
|
||
|
// # Formatting constants.
|
||
|
var singleBinHeight = 20; // The distance between tick marks, in px
|
||
|
|
||
|
var vMargin = 8; // If 1st tick mark starts at top of gradient, how
|
||
|
// many extra px are needed for the top half of the
|
||
|
// 1st label? (ditto for last tick mark/label)
|
||
|
|
||
|
var tickWidth = 4; // How wide should tick marks be, in px?
|
||
|
|
||
|
var labelPadding = 6; // How much distance to reserve for tick mark?
|
||
|
// (Must be >= tickWidth)
|
||
|
// # Derived formatting parameters.
|
||
|
// What's the height of a single bin, in percentage (of gradient height)?
|
||
|
// It might not just be 1/(n-1), if the gradient extends past the tick
|
||
|
// marks (which can be the case for pretty cut points).
|
||
|
|
||
|
var singleBinPct = (options.extra.p_n - options.extra.p_1) / (labels.length - 1); // Each bin is `singleBinHeight` high. How tall is the gradient?
|
||
|
|
||
|
var totalHeight = 1 / singleBinPct * singleBinHeight + 1; // How far should the first tick be shifted down, relative to the top
|
||
|
// of the gradient?
|
||
|
|
||
|
var tickOffset = singleBinHeight / singleBinPct * options.extra.p_1;
|
||
|
gradSpan = (0, _jquery2["default"])("<span/>").css({
|
||
|
"background": "linear-gradient(" + colors + ")",
|
||
|
"opacity": options.opacity,
|
||
|
"height": totalHeight + "px",
|
||
|
"width": "18px",
|
||
|
"display": "block",
|
||
|
"margin-top": vMargin + "px"
|
||
|
});
|
||
|
var leftDiv = (0, _jquery2["default"])("<div/>").css("float", "left"),
|
||
|
rightDiv = (0, _jquery2["default"])("<div/>").css("float", "left");
|
||
|
leftDiv.append(gradSpan);
|
||
|
(0, _jquery2["default"])(div).append(leftDiv).append(rightDiv).append((0, _jquery2["default"])("<br>")); // Have to attach the div to the body at this early point, so that the
|
||
|
// svg text getComputedTextLength() actually works, below.
|
||
|
|
||
|
document.body.appendChild(div);
|
||
|
var ns = "http://www.w3.org/2000/svg";
|
||
|
var svg = document.createElementNS(ns, "svg");
|
||
|
rightDiv.append(svg);
|
||
|
var g = document.createElementNS(ns, "g");
|
||
|
(0, _jquery2["default"])(g).attr("transform", "translate(0, " + vMargin + ")");
|
||
|
svg.appendChild(g); // max label width needed to set width of svg, and right-justify text
|
||
|
|
||
|
var maxLblWidth = 0; // Create tick marks and labels
|
||
|
|
||
|
_jquery2["default"].each(labels, function (i, label) {
|
||
|
var y = tickOffset + i * singleBinHeight + 0.5;
|
||
|
var thisLabel = document.createElementNS(ns, "text");
|
||
|
(0, _jquery2["default"])(thisLabel).text(labels[i]).attr("y", y).attr("dx", labelPadding).attr("dy", "0.5ex");
|
||
|
g.appendChild(thisLabel);
|
||
|
maxLblWidth = Math.max(maxLblWidth, thisLabel.getComputedTextLength());
|
||
|
var thisTick = document.createElementNS(ns, "line");
|
||
|
(0, _jquery2["default"])(thisTick).attr("x1", 0).attr("x2", tickWidth).attr("y1", y).attr("y2", y).attr("stroke-width", 1);
|
||
|
g.appendChild(thisTick);
|
||
|
}); // Now that we know the max label width, we can right-justify
|
||
|
|
||
|
|
||
|
(0, _jquery2["default"])(svg).find("text").attr("dx", labelPadding + maxLblWidth).attr("text-anchor", "end"); // Final size for <svg>
|
||
|
|
||
|
(0, _jquery2["default"])(svg).css({
|
||
|
width: maxLblWidth + labelPadding + "px",
|
||
|
height: totalHeight + vMargin * 2 + "px"
|
||
|
});
|
||
|
|
||
|
if (options.na_color && _jquery2["default"].inArray(options.na_label, labels) < 0) {
|
||
|
(0, _jquery2["default"])(div).append("<div><i style=\"" + "background:" + options.na_color + ";opacity:" + options.opacity + ";margin-right:" + labelPadding + "px" + ";\"></i>" + options.na_label + "</div>");
|
||
|
}
|
||
|
} else {
|
||
|
if (options.na_color && _jquery2["default"].inArray(options.na_label, labels) < 0) {
|
||
|
colors.push(options.na_color);
|
||
|
labels.push(options.na_label);
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < colors.length; i++) {
|
||
|
legendHTML += "<i style=\"background:" + colors[i] + ";opacity:" + options.opacity + "\"></i> " + labels[i] + "<br>";
|
||
|
}
|
||
|
|
||
|
div.innerHTML = legendHTML;
|
||
|
}
|
||
|
|
||
|
if (options.title) (0, _jquery2["default"])(div).prepend("<div style=\"margin-bottom:3px\"><strong>" + options.title + "</strong></div>");
|
||
|
return div;
|
||
|
};
|
||
|
|
||
|
if (options.group) {
|
||
|
// Auto generate a layerID if not provided
|
||
|
if (!options.layerId) {
|
||
|
options.layerId = _leaflet2["default"].Util.stamp(legend);
|
||
|
}
|
||
|
|
||
|
var map = this;
|
||
|
map.on("overlayadd", function (e) {
|
||
|
if (e.name === options.group) {
|
||
|
map.controls.add(legend, options.layerId);
|
||
|
}
|
||
|
});
|
||
|
map.on("overlayremove", function (e) {
|
||
|
if (e.name === options.group) {
|
||
|
map.controls.remove(options.layerId);
|
||
|
}
|
||
|
});
|
||
|
map.on("groupadd", function (e) {
|
||
|
if (e.name === options.group) {
|
||
|
map.controls.add(legend, options.layerId);
|
||
|
}
|
||
|
});
|
||
|
map.on("groupremove", function (e) {
|
||
|
if (e.name === options.group) {
|
||
|
map.controls.remove(options.layerId);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
this.controls.add(legend, options.layerId);
|
||
|
};
|
||
|
|
||
|
methods.addLayersControl = function (baseGroups, overlayGroups, options) {
|
||
|
var _this4 = this;
|
||
|
|
||
|
// Only allow one layers control at a time
|
||
|
methods.removeLayersControl.call(this);
|
||
|
var firstLayer = true;
|
||
|
var base = {};
|
||
|
|
||
|
_jquery2["default"].each((0, _util.asArray)(baseGroups), function (i, g) {
|
||
|
var layer = _this4.layerManager.getLayerGroup(g, true);
|
||
|
|
||
|
if (layer) {
|
||
|
base[g] = layer; // Check if >1 base layers are visible; if so, hide all but the first one
|
||
|
|
||
|
if (_this4.hasLayer(layer)) {
|
||
|
if (firstLayer) {
|
||
|
firstLayer = false;
|
||
|
} else {
|
||
|
_this4.removeLayer(layer);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
var overlay = {};
|
||
|
|
||
|
_jquery2["default"].each((0, _util.asArray)(overlayGroups), function (i, g) {
|
||
|
var layer = _this4.layerManager.getLayerGroup(g, true);
|
||
|
|
||
|
if (layer) {
|
||
|
overlay[g] = layer;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
this.currentLayersControl = _leaflet2["default"].control.layers(base, overlay, options);
|
||
|
this.addControl(this.currentLayersControl);
|
||
|
};
|
||
|
|
||
|
methods.removeLayersControl = function () {
|
||
|
if (this.currentLayersControl) {
|
||
|
this.removeControl(this.currentLayersControl);
|
||
|
this.currentLayersControl = null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.addScaleBar = function (options) {
|
||
|
// Only allow one scale bar at a time
|
||
|
methods.removeScaleBar.call(this);
|
||
|
|
||
|
var scaleBar = _leaflet2["default"].control.scale(options).addTo(this);
|
||
|
|
||
|
this.currentScaleBar = scaleBar;
|
||
|
};
|
||
|
|
||
|
methods.removeScaleBar = function () {
|
||
|
if (this.currentScaleBar) {
|
||
|
this.currentScaleBar.remove();
|
||
|
this.currentScaleBar = null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.hideGroup = function (group) {
|
||
|
var _this5 = this;
|
||
|
|
||
|
_jquery2["default"].each((0, _util.asArray)(group), function (i, g) {
|
||
|
var layer = _this5.layerManager.getLayerGroup(g, true);
|
||
|
|
||
|
if (layer) {
|
||
|
_this5.removeLayer(layer);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
methods.showGroup = function (group) {
|
||
|
var _this6 = this;
|
||
|
|
||
|
_jquery2["default"].each((0, _util.asArray)(group), function (i, g) {
|
||
|
var layer = _this6.layerManager.getLayerGroup(g, true);
|
||
|
|
||
|
if (layer) {
|
||
|
_this6.addLayer(layer);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
function setupShowHideGroupsOnZoom(map) {
|
||
|
if (map.leafletr._hasInitializedShowHideGroups) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
map.leafletr._hasInitializedShowHideGroups = true;
|
||
|
|
||
|
function setVisibility(layer, visible, group) {
|
||
|
if (visible !== map.hasLayer(layer)) {
|
||
|
if (visible) {
|
||
|
map.addLayer(layer);
|
||
|
map.fire("groupadd", {
|
||
|
"name": group,
|
||
|
"layer": layer
|
||
|
});
|
||
|
} else {
|
||
|
map.removeLayer(layer);
|
||
|
map.fire("groupremove", {
|
||
|
"name": group,
|
||
|
"layer": layer
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function showHideGroupsOnZoom() {
|
||
|
if (!map.layerManager) return;
|
||
|
var zoom = map.getZoom();
|
||
|
map.layerManager.getAllGroupNames().forEach(function (group) {
|
||
|
var layer = map.layerManager.getLayerGroup(group, false);
|
||
|
|
||
|
if (layer && typeof layer.zoomLevels !== "undefined") {
|
||
|
setVisibility(layer, layer.zoomLevels === true || layer.zoomLevels.indexOf(zoom) >= 0, group);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
map.showHideGroupsOnZoom = showHideGroupsOnZoom;
|
||
|
map.on("zoomend", showHideGroupsOnZoom);
|
||
|
}
|
||
|
|
||
|
methods.setGroupOptions = function (group, options) {
|
||
|
var _this7 = this;
|
||
|
|
||
|
_jquery2["default"].each((0, _util.asArray)(group), function (i, g) {
|
||
|
var layer = _this7.layerManager.getLayerGroup(g, true); // This slightly tortured check is because 0 is a valid value for zoomLevels
|
||
|
|
||
|
|
||
|
if (typeof options.zoomLevels !== "undefined" && options.zoomLevels !== null) {
|
||
|
layer.zoomLevels = (0, _util.asArray)(options.zoomLevels);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
setupShowHideGroupsOnZoom(this);
|
||
|
this.showHideGroupsOnZoom();
|
||
|
};
|
||
|
|
||
|
methods.addRasterImage = function (uri, bounds, layerId, group, options) {
|
||
|
// uri is a data URI containing an image. We want to paint this image as a
|
||
|
// layer at (top-left) bounds[0] to (bottom-right) bounds[1].
|
||
|
// We can't simply use ImageOverlay, as it uses bilinear scaling which looks
|
||
|
// awful as you zoom in (and sometimes shifts positions or disappears).
|
||
|
// Instead, we'll use a TileLayer.Canvas to draw pieces of the image.
|
||
|
// First, some helper functions.
|
||
|
// degree2tile converts latitude, longitude, and zoom to x and y tile
|
||
|
// numbers. The tile numbers returned can be non-integral, as there's no
|
||
|
// reason to expect that the lat/lng inputs are exactly on the border of two
|
||
|
// tiles.
|
||
|
//
|
||
|
// We'll use this to convert the bounds we got from the server, into coords
|
||
|
// in tile-space at a given zoom level. Note that once we do the conversion,
|
||
|
// we don't to do any more trigonometry to convert between pixel coordinates
|
||
|
// and tile coordinates; the source image pixel coords, destination canvas
|
||
|
// pixel coords, and tile coords all can be scaled linearly.
|
||
|
function degree2tile(lat, lng, zoom) {
|
||
|
// See http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
|
||
|
var latRad = lat * Math.PI / 180;
|
||
|
var n = Math.pow(2, zoom);
|
||
|
var x = (lng + 180) / 360 * n;
|
||
|
var y = (1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * n;
|
||
|
return {
|
||
|
x: x,
|
||
|
y: y
|
||
|
};
|
||
|
} // Given a range [from,to) and either one or two numbers, returns true if
|
||
|
// there is any overlap between [x,x1) and the range--or if x1 is omitted,
|
||
|
// then returns true if x is within [from,to).
|
||
|
|
||
|
|
||
|
function overlap(from, to, x,
|
||
|
/* optional */
|
||
|
x1) {
|
||
|
if (arguments.length == 3) x1 = x;
|
||
|
return x < to && x1 >= from;
|
||
|
}
|
||
|
|
||
|
function getCanvasSmoothingProperty(ctx) {
|
||
|
var candidates = ["imageSmoothingEnabled", "mozImageSmoothingEnabled", "webkitImageSmoothingEnabled", "msImageSmoothingEnabled"];
|
||
|
|
||
|
for (var i = 0; i < candidates.length; i++) {
|
||
|
if (typeof ctx[candidates[i]] !== "undefined") {
|
||
|
return candidates[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
} // Our general strategy is to:
|
||
|
// 1. Load the data URI in an Image() object, so we can get its pixel
|
||
|
// dimensions and the underlying image data. (We could have done this
|
||
|
// by not encoding as PNG at all but just send an array of RGBA values
|
||
|
// from the server, but that would inflate the JSON too much.)
|
||
|
// 2. Create a hidden canvas that we use just to extract the image data
|
||
|
// from the Image (using Context2D.getImageData()).
|
||
|
// 3. Create a TileLayer.Canvas and add it to the map.
|
||
|
// We want to synchronously create and attach the TileLayer.Canvas (so an
|
||
|
// immediate call to clearRasters() will be respected, for example), but
|
||
|
// Image loads its data asynchronously. Fortunately we can resolve this
|
||
|
// by putting TileLayer.Canvas into async mode, which will let us create
|
||
|
// and attach the layer but have it wait until the image is loaded before
|
||
|
// it actually draws anything.
|
||
|
// These are the variables that we will populate once the image is loaded.
|
||
|
|
||
|
|
||
|
var imgData = null; // 1d row-major array, four [0-255] integers per pixel
|
||
|
|
||
|
var imgDataMipMapper = null;
|
||
|
var w = null; // image width in pixels
|
||
|
|
||
|
var h = null; // image height in pixels
|
||
|
// We'll use this array to store callbacks that need to be invoked once
|
||
|
// imgData, w, and h have been resolved.
|
||
|
|
||
|
var imgDataCallbacks = []; // Consumers of imgData, w, and h can call this to be notified when data
|
||
|
// is available.
|
||
|
|
||
|
function getImageData(callback) {
|
||
|
if (imgData != null) {
|
||
|
// Must not invoke the callback immediately; it's too confusing and
|
||
|
// fragile to have a function invoke the callback *either* immediately
|
||
|
// or in the future. Better to be consistent here.
|
||
|
setTimeout(function () {
|
||
|
callback(imgData, w, h, imgDataMipMapper);
|
||
|
}, 0);
|
||
|
} else {
|
||
|
imgDataCallbacks.push(callback);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var img = new Image();
|
||
|
|
||
|
img.onload = function () {
|
||
|
// Save size
|
||
|
w = img.width;
|
||
|
h = img.height; // Create a dummy canvas to extract the image data
|
||
|
|
||
|
var imgDataCanvas = document.createElement("canvas");
|
||
|
imgDataCanvas.width = w;
|
||
|
imgDataCanvas.height = h;
|
||
|
imgDataCanvas.style.display = "none";
|
||
|
document.body.appendChild(imgDataCanvas);
|
||
|
var imgDataCtx = imgDataCanvas.getContext("2d");
|
||
|
imgDataCtx.drawImage(img, 0, 0); // Save the image data.
|
||
|
|
||
|
imgData = imgDataCtx.getImageData(0, 0, w, h).data;
|
||
|
imgDataMipMapper = new _mipmapper2["default"](img); // Done with the canvas, remove it from the page so it can be gc'd.
|
||
|
|
||
|
document.body.removeChild(imgDataCanvas); // Alert any getImageData callers who are waiting.
|
||
|
|
||
|
for (var i = 0; i < imgDataCallbacks.length; i++) {
|
||
|
imgDataCallbacks[i](imgData, w, h, imgDataMipMapper);
|
||
|
}
|
||
|
|
||
|
imgDataCallbacks = [];
|
||
|
};
|
||
|
|
||
|
img.src = uri;
|
||
|
|
||
|
var canvasTiles = _leaflet2["default"].gridLayer(Object.assign({}, options, {
|
||
|
detectRetina: true,
|
||
|
async: true
|
||
|
})); // NOTE: The done() function MUST NOT be invoked until after the current
|
||
|
// tick; done() looks in Leaflet's tile cache for the current tile, and
|
||
|
// since it's still being constructed, it won't be found.
|
||
|
|
||
|
|
||
|
canvasTiles.createTile = function (tilePoint, done) {
|
||
|
var zoom = tilePoint.z;
|
||
|
|
||
|
var canvas = _leaflet2["default"].DomUtil.create("canvas");
|
||
|
|
||
|
var error; // setup tile width and height according to the options
|
||
|
|
||
|
var size = this.getTileSize();
|
||
|
canvas.width = size.x;
|
||
|
canvas.height = size.y;
|
||
|
getImageData(function (imgData, w, h, mipmapper) {
|
||
|
try {
|
||
|
// The Context2D we'll being drawing onto. It's always 256x256.
|
||
|
var ctx = canvas.getContext("2d"); // Convert our image data's top-left and bottom-right locations into
|
||
|
// x/y tile coordinates. This is essentially doing a spherical mercator
|
||
|
// projection, then multiplying by 2^zoom.
|
||
|
|
||
|
var topLeft = degree2tile(bounds[0][0], bounds[0][1], zoom);
|
||
|
var bottomRight = degree2tile(bounds[1][0], bounds[1][1], zoom); // The size of the image in x/y tile coordinates.
|
||
|
|
||
|
var extent = {
|
||
|
x: bottomRight.x - topLeft.x,
|
||
|
y: bottomRight.y - topLeft.y
|
||
|
}; // Short circuit if tile is totally disjoint from image.
|
||
|
|
||
|
if (!overlap(tilePoint.x, tilePoint.x + 1, topLeft.x, bottomRight.x)) return;
|
||
|
if (!overlap(tilePoint.y, tilePoint.y + 1, topLeft.y, bottomRight.y)) return; // The linear resolution of the tile we're drawing is always 256px per tile unit.
|
||
|
// If the linear resolution (in either direction) of the image is less than 256px
|
||
|
// per tile unit, then use nearest neighbor; otherwise, use the canvas's built-in
|
||
|
// scaling.
|
||
|
|
||
|
var imgRes = {
|
||
|
x: w / extent.x,
|
||
|
y: h / extent.y
|
||
|
}; // We can do the actual drawing in one of three ways:
|
||
|
// - Call drawImage(). This is easy and fast, and results in smooth
|
||
|
// interpolation (bilinear?). This is what we want when we are
|
||
|
// reducing the image from its native size.
|
||
|
// - Call drawImage() with imageSmoothingEnabled=false. This is easy
|
||
|
// and fast and gives us nearest-neighbor interpolation, which is what
|
||
|
// we want when enlarging the image. However, it's unsupported on many
|
||
|
// browsers (including QtWebkit).
|
||
|
// - Do a manual nearest-neighbor interpolation. This is what we'll fall
|
||
|
// back to when enlarging, and imageSmoothingEnabled isn't supported.
|
||
|
// In theory it's slower, but still pretty fast on my machine, and the
|
||
|
// results look the same AFAICT.
|
||
|
// Is imageSmoothingEnabled supported? If so, we can let canvas do
|
||
|
// nearest-neighbor interpolation for us.
|
||
|
|
||
|
var smoothingProperty = getCanvasSmoothingProperty(ctx);
|
||
|
|
||
|
if (smoothingProperty || imgRes.x >= 256 && imgRes.y >= 256) {
|
||
|
// Use built-in scaling
|
||
|
// Turn off anti-aliasing if necessary
|
||
|
if (smoothingProperty) {
|
||
|
ctx[smoothingProperty] = imgRes.x >= 256 && imgRes.y >= 256;
|
||
|
} // Don't necessarily draw with the full-size image; if we're
|
||
|
// downscaling, use the mipmapper to get a pre-downscaled image
|
||
|
// (see comments on Mipmapper class for why this matters).
|
||
|
|
||
|
|
||
|
mipmapper.getBySize(extent.x * 256, extent.y * 256, function (mip) {
|
||
|
// It's possible that the image will go off the edge of the canvas--
|
||
|
// that's OK, the canvas should clip appropriately.
|
||
|
ctx.drawImage(mip, // Convert abs tile coords to rel tile coords, then *256 to convert
|
||
|
// to rel pixel coords
|
||
|
(topLeft.x - tilePoint.x) * 256, (topLeft.y - tilePoint.y) * 256, // Always draw the whole thing and let canvas clip; so we can just
|
||
|
// convert from size in tile coords straight to pixels
|
||
|
extent.x * 256, extent.y * 256);
|
||
|
});
|
||
|
} else {
|
||
|
// Use manual nearest-neighbor interpolation
|
||
|
// Calculate the source image pixel coordinates that correspond with
|
||
|
// the top-left and bottom-right of this tile. (If the source image
|
||
|
// only partially overlaps the tile, we use max/min to limit the
|
||
|
// sourceStart/End to only reflect the overlapping portion.)
|
||
|
var sourceStart = {
|
||
|
x: Math.max(0, Math.floor((tilePoint.x - topLeft.x) * imgRes.x)),
|
||
|
y: Math.max(0, Math.floor((tilePoint.y - topLeft.y) * imgRes.y))
|
||
|
};
|
||
|
var sourceEnd = {
|
||
|
x: Math.min(w, Math.ceil((tilePoint.x + 1 - topLeft.x) * imgRes.x)),
|
||
|
y: Math.min(h, Math.ceil((tilePoint.y + 1 - topLeft.y) * imgRes.y))
|
||
|
}; // The size, in dest pixels, that each source pixel should occupy.
|
||
|
// This might be greater or less than 1 (e.g. if x and y resolution
|
||
|
// are very different).
|
||
|
|
||
|
var pixelSize = {
|
||
|
x: 256 / imgRes.x,
|
||
|
y: 256 / imgRes.y
|
||
|
}; // For each pixel in the source image that overlaps the tile...
|
||
|
|
||
|
for (var row = sourceStart.y; row < sourceEnd.y; row++) {
|
||
|
for (var col = sourceStart.x; col < sourceEnd.x; col++) {
|
||
|
// ...extract the pixel data...
|
||
|
var i = (row * w + col) * 4;
|
||
|
var r = imgData[i];
|
||
|
var g = imgData[i + 1];
|
||
|
var b = imgData[i + 2];
|
||
|
var a = imgData[i + 3];
|
||
|
ctx.fillStyle = "rgba(" + [r, g, b, a / 255].join(",") + ")"; // ...calculate the corresponding pixel coord in the dest image
|
||
|
// where it should be drawn...
|
||
|
|
||
|
var pixelPos = {
|
||
|
x: (col / imgRes.x + topLeft.x - tilePoint.x) * 256,
|
||
|
y: (row / imgRes.y + topLeft.y - tilePoint.y) * 256
|
||
|
}; // ...and draw a rectangle there.
|
||
|
|
||
|
ctx.fillRect(Math.round(pixelPos.x), Math.round(pixelPos.y), // Looks crazy, but this is necessary to prevent rounding from
|
||
|
// causing overlap between this rect and its neighbors. The
|
||
|
// minuend is the location of the next pixel, while the
|
||
|
// subtrahend is the position of the current pixel (to turn an
|
||
|
// absolute coordinate to a width/height). Yes, I had to look
|
||
|
// up minuend and subtrahend.
|
||
|
Math.round(pixelPos.x + pixelSize.x) - Math.round(pixelPos.x), Math.round(pixelPos.y + pixelSize.y) - Math.round(pixelPos.y));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} catch (e) {
|
||
|
error = e;
|
||
|
} finally {
|
||
|
done(error, canvas);
|
||
|
}
|
||
|
});
|
||
|
return canvas;
|
||
|
};
|
||
|
|
||
|
this.layerManager.addLayer(canvasTiles, "image", layerId, group);
|
||
|
};
|
||
|
|
||
|
methods.removeImage = function (layerId) {
|
||
|
this.layerManager.removeLayer("image", layerId);
|
||
|
};
|
||
|
|
||
|
methods.clearImages = function () {
|
||
|
this.layerManager.clearLayers("image");
|
||
|
};
|
||
|
|
||
|
methods.addMeasure = function (options) {
|
||
|
// if a measureControl already exists, then remove it and
|
||
|
// replace with a new one
|
||
|
methods.removeMeasure.call(this);
|
||
|
this.measureControl = _leaflet2["default"].control.measure(options);
|
||
|
this.addControl(this.measureControl);
|
||
|
};
|
||
|
|
||
|
methods.removeMeasure = function () {
|
||
|
if (this.measureControl) {
|
||
|
this.removeControl(this.measureControl);
|
||
|
this.measureControl = null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.addSelect = function (ctGroup) {
|
||
|
var _this8 = this;
|
||
|
|
||
|
methods.removeSelect.call(this);
|
||
|
this._selectButton = _leaflet2["default"].easyButton({
|
||
|
states: [{
|
||
|
stateName: "select-inactive",
|
||
|
icon: "ion-qr-scanner",
|
||
|
title: "Make a selection",
|
||
|
onClick: function onClick(btn, map) {
|
||
|
btn.state("select-active");
|
||
|
_this8._locationFilter = new _leaflet2["default"].LocationFilter2();
|
||
|
|
||
|
if (ctGroup) {
|
||
|
var selectionHandle = new global.crosstalk.SelectionHandle(ctGroup);
|
||
|
selectionHandle.on("change", function (e) {
|
||
|
if (e.sender !== selectionHandle) {
|
||
|
if (_this8._locationFilter) {
|
||
|
_this8._locationFilter.disable();
|
||
|
|
||
|
btn.state("select-inactive");
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
var handler = function handler(e) {
|
||
|
_this8.layerManager.brush(_this8._locationFilter.getBounds(), {
|
||
|
sender: selectionHandle
|
||
|
});
|
||
|
};
|
||
|
|
||
|
_this8._locationFilter.on("enabled", handler);
|
||
|
|
||
|
_this8._locationFilter.on("change", handler);
|
||
|
|
||
|
_this8._locationFilter.on("disabled", function () {
|
||
|
selectionHandle.close();
|
||
|
_this8._locationFilter = null;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
_this8._locationFilter.addTo(map);
|
||
|
}
|
||
|
}, {
|
||
|
stateName: "select-active",
|
||
|
icon: "ion-close-round",
|
||
|
title: "Dismiss selection",
|
||
|
onClick: function onClick(btn, map) {
|
||
|
btn.state("select-inactive");
|
||
|
|
||
|
_this8._locationFilter.disable(); // If explicitly dismissed, clear the crosstalk selections
|
||
|
|
||
|
|
||
|
_this8.layerManager.unbrush();
|
||
|
}
|
||
|
}]
|
||
|
});
|
||
|
|
||
|
this._selectButton.addTo(this);
|
||
|
};
|
||
|
|
||
|
methods.removeSelect = function () {
|
||
|
if (this._locationFilter) {
|
||
|
this._locationFilter.disable();
|
||
|
}
|
||
|
|
||
|
if (this._selectButton) {
|
||
|
this.removeControl(this._selectButton);
|
||
|
this._selectButton = null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
methods.createMapPane = function (name, zIndex) {
|
||
|
this.createPane(name);
|
||
|
this.getPane(name).style.zIndex = zIndex;
|
||
|
};
|
||
|
|
||
|
|
||
|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
|
},{"./cluster-layer-store":1,"./crs_utils":3,"./dataframe":4,"./global/htmlwidgets":8,"./global/jquery":9,"./global/leaflet":10,"./global/shiny":12,"./mipmapper":16,"./util":17}],16:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
|
||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
||
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||
|
|
||
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||
|
|
||
|
// This class simulates a mipmap, which shrinks images by powers of two. This
|
||
|
// stepwise reduction results in "pixel-perfect downscaling" (where every
|
||
|
// pixel of the original image has some contribution to the downscaled image)
|
||
|
// as opposed to a single-step downscaling which will discard a lot of data
|
||
|
// (and with sparse images at small scales can give very surprising results).
|
||
|
var Mipmapper = /*#__PURE__*/function () {
|
||
|
function Mipmapper(img) {
|
||
|
_classCallCheck(this, Mipmapper);
|
||
|
|
||
|
this._layers = [img];
|
||
|
} // The various functions on this class take a callback function BUT MAY OR MAY
|
||
|
// NOT actually behave asynchronously.
|
||
|
|
||
|
|
||
|
_createClass(Mipmapper, [{
|
||
|
key: "getBySize",
|
||
|
value: function getBySize(desiredWidth, desiredHeight, callback) {
|
||
|
var _this = this;
|
||
|
|
||
|
var i = 0;
|
||
|
var lastImg = this._layers[0];
|
||
|
|
||
|
var testNext = function testNext() {
|
||
|
_this.getByIndex(i, function (img) {
|
||
|
// If current image is invalid (i.e. too small to be rendered) or
|
||
|
// it's smaller than what we wanted, return the last known good image.
|
||
|
if (!img || img.width < desiredWidth || img.height < desiredHeight) {
|
||
|
callback(lastImg);
|
||
|
return;
|
||
|
} else {
|
||
|
lastImg = img;
|
||
|
i++;
|
||
|
testNext();
|
||
|
return;
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
testNext();
|
||
|
}
|
||
|
}, {
|
||
|
key: "getByIndex",
|
||
|
value: function getByIndex(i, callback) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
if (this._layers[i]) {
|
||
|
callback(this._layers[i]);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.getByIndex(i - 1, function (prevImg) {
|
||
|
if (!prevImg) {
|
||
|
// prevImg could not be calculated (too small, possibly)
|
||
|
callback(null);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (prevImg.width < 2 || prevImg.height < 2) {
|
||
|
// Can't reduce this image any further
|
||
|
callback(null);
|
||
|
return;
|
||
|
} // If reduce ever becomes truly asynchronous, we should stuff a promise or
|
||
|
// something into this._layers[i] before calling this.reduce(), to prevent
|
||
|
// redundant reduce operations from happening.
|
||
|
|
||
|
|
||
|
_this2.reduce(prevImg, function (reducedImg) {
|
||
|
_this2._layers[i] = reducedImg;
|
||
|
callback(reducedImg);
|
||
|
return;
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: "reduce",
|
||
|
value: function reduce(img, callback) {
|
||
|
var imgDataCanvas = document.createElement("canvas");
|
||
|
imgDataCanvas.width = Math.ceil(img.width / 2);
|
||
|
imgDataCanvas.height = Math.ceil(img.height / 2);
|
||
|
imgDataCanvas.style.display = "none";
|
||
|
document.body.appendChild(imgDataCanvas);
|
||
|
|
||
|
try {
|
||
|
var imgDataCtx = imgDataCanvas.getContext("2d");
|
||
|
imgDataCtx.drawImage(img, 0, 0, img.width / 2, img.height / 2);
|
||
|
callback(imgDataCanvas);
|
||
|
} finally {
|
||
|
document.body.removeChild(imgDataCanvas);
|
||
|
}
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return Mipmapper;
|
||
|
}();
|
||
|
|
||
|
exports["default"] = Mipmapper;
|
||
|
|
||
|
|
||
|
},{}],17:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.log = log;
|
||
|
exports.recycle = recycle;
|
||
|
exports.asArray = asArray;
|
||
|
|
||
|
function log(message) {
|
||
|
/* eslint-disable no-console */
|
||
|
if (console && console.log) console.log(message);
|
||
|
/* eslint-enable no-console */
|
||
|
}
|
||
|
|
||
|
function recycle(values, length, inPlace) {
|
||
|
if (length === 0 && !inPlace) return [];
|
||
|
|
||
|
if (!(values instanceof Array)) {
|
||
|
if (inPlace) {
|
||
|
throw new Error("Can't do in-place recycling of a non-Array value");
|
||
|
}
|
||
|
|
||
|
values = [values];
|
||
|
}
|
||
|
|
||
|
if (typeof length === "undefined") length = values.length;
|
||
|
var dest = inPlace ? values : [];
|
||
|
var origLength = values.length;
|
||
|
|
||
|
while (dest.length < length) {
|
||
|
dest.push(values[dest.length % origLength]);
|
||
|
}
|
||
|
|
||
|
if (dest.length > length) {
|
||
|
dest.splice(length, dest.length - length);
|
||
|
}
|
||
|
|
||
|
return dest;
|
||
|
}
|
||
|
|
||
|
function asArray(value) {
|
||
|
if (value instanceof Array) return value;else return [value];
|
||
|
}
|
||
|
|
||
|
|
||
|
},{}]},{},[13]);
|
||
|
</script>
|
||
|
<script>(function (root, factory) {
|
||
|
if (typeof define === 'function' && define.amd) {
|
||
|
// AMD. Register as an anonymous module.
|
||
|
define(['leaflet'], factory);
|
||
|
} else if (typeof modules === 'object' && module.exports) {
|
||
|
// define a Common JS module that relies on 'leaflet'
|
||
|
module.exports = factory(require('leaflet'));
|
||
|
} else {
|
||
|
// Assume Leaflet is loaded into global object L already
|
||
|
factory(L);
|
||
|
}
|
||
|
}(this, function (L) {
|
||
|
'use strict';
|
||
|
|
||
|
L.TileLayer.Provider = L.TileLayer.extend({
|
||
|
initialize: function (arg, options) {
|
||
|
var providers = L.TileLayer.Provider.providers;
|
||
|
|
||
|
var parts = arg.split('.');
|
||
|
|
||
|
var providerName = parts[0];
|
||
|
var variantName = parts[1];
|
||
|
|
||
|
if (!providers[providerName]) {
|
||
|
throw 'No such provider (' + providerName + ')';
|
||
|
}
|
||
|
|
||
|
var provider = {
|
||
|
url: providers[providerName].url,
|
||
|
options: providers[providerName].options
|
||
|
};
|
||
|
|
||
|
// overwrite values in provider from variant.
|
||
|
if (variantName && 'variants' in providers[providerName]) {
|
||
|
if (!(variantName in providers[providerName].variants)) {
|
||
|
throw 'No such variant of ' + providerName + ' (' + variantName + ')';
|
||
|
}
|
||
|
var variant = providers[providerName].variants[variantName];
|
||
|
var variantOptions;
|
||
|
if (typeof variant === 'string') {
|
||
|
variantOptions = {
|
||
|
variant: variant
|
||
|
};
|
||
|
} else {
|
||
|
variantOptions = variant.options;
|
||
|
}
|
||
|
provider = {
|
||
|
url: variant.url || provider.url,
|
||
|
options: L.Util.extend({}, provider.options, variantOptions)
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// replace attribution placeholders with their values from toplevel provider attribution,
|
||
|
// recursively
|
||
|
var attributionReplacer = function (attr) {
|
||
|
if (attr.indexOf('{attribution.') === -1) {
|
||
|
return attr;
|
||
|
}
|
||
|
return attr.replace(/\{attribution.(\w*)\}/g,
|
||
|
function (match, attributionName) {
|
||
|
return attributionReplacer(providers[attributionName].options.attribution);
|
||
|
}
|
||
|
);
|
||
|
};
|
||
|
provider.options.attribution = attributionReplacer(provider.options.attribution);
|
||
|
|
||
|
// Compute final options combining provider options with any user overrides
|
||
|
var layerOpts = L.Util.extend({}, provider.options, options);
|
||
|
L.TileLayer.prototype.initialize.call(this, provider.url, layerOpts);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Definition of providers.
|
||
|
* see http://leafletjs.com/reference.html#tilelayer for options in the options map.
|
||
|
*/
|
||
|
|
||
|
L.TileLayer.Provider.providers = {
|
||
|
OpenStreetMap: {
|
||
|
url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 19,
|
||
|
attribution:
|
||
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||
|
},
|
||
|
variants: {
|
||
|
Mapnik: {},
|
||
|
DE: {
|
||
|
url: 'https://tile.openstreetmap.de/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 18
|
||
|
}
|
||
|
},
|
||
|
CH: {
|
||
|
url: 'https://tile.osm.ch/switzerland/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 18,
|
||
|
bounds: [[45, 5], [48, 11]]
|
||
|
}
|
||
|
},
|
||
|
France: {
|
||
|
url: 'https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 20,
|
||
|
attribution: '© OpenStreetMap France | {attribution.OpenStreetMap}'
|
||
|
}
|
||
|
},
|
||
|
HOT: {
|
||
|
url: 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'{attribution.OpenStreetMap}, ' +
|
||
|
'Tiles style by <a href="https://www.hotosm.org/" target="_blank">Humanitarian OpenStreetMap Team</a> ' +
|
||
|
'hosted by <a href="https://openstreetmap.fr/" target="_blank">OpenStreetMap France</a>'
|
||
|
}
|
||
|
},
|
||
|
BZH: {
|
||
|
url: 'https://tile.openstreetmap.bzh/br/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
attribution: '{attribution.OpenStreetMap}, Tiles courtesy of <a href="http://www.openstreetmap.bzh/" target="_blank">Breton OpenStreetMap Team</a>',
|
||
|
bounds: [[46.2, -5.5], [50, 0.7]]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
MapTilesAPI: {
|
||
|
url: 'https://maptiles.p.rapidapi.com/{variant}/{z}/{x}/{y}.png?rapidapi-key={apikey}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="http://www.maptilesapi.com/">MapTiles API</a>, {attribution.OpenStreetMap}',
|
||
|
variant: 'en/map/v1',
|
||
|
// Get your own MapTiles API access token here : https://www.maptilesapi.com/
|
||
|
// NB : this is a demonstration key that comes with no guarantee and not to be used in production
|
||
|
apikey: '<insert your api key here>',
|
||
|
maxZoom: 19
|
||
|
},
|
||
|
variants: {
|
||
|
OSMEnglish: {
|
||
|
options: {
|
||
|
variant: 'en/map/v1'
|
||
|
}
|
||
|
},
|
||
|
OSMFrancais: {
|
||
|
options: {
|
||
|
variant: 'fr/map/v1'
|
||
|
}
|
||
|
},
|
||
|
OSMEspagnol: {
|
||
|
options: {
|
||
|
variant: 'es/map/v1'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
OpenSeaMap: {
|
||
|
url: 'https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
attribution: 'Map data: © <a href="http://www.openseamap.org">OpenSeaMap</a> contributors'
|
||
|
}
|
||
|
},
|
||
|
OPNVKarte: {
|
||
|
url: 'https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 18,
|
||
|
attribution: 'Map <a href="https://memomaps.de/">memomaps.de</a> <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, map data {attribution.OpenStreetMap}'
|
||
|
}
|
||
|
},
|
||
|
OpenTopoMap: {
|
||
|
url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 17,
|
||
|
attribution: 'Map data: {attribution.OpenStreetMap}, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
|
||
|
}
|
||
|
},
|
||
|
OpenRailwayMap: {
|
||
|
url: 'https://{s}.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 19,
|
||
|
attribution: 'Map data: {attribution.OpenStreetMap} | Map style: © <a href="https://www.OpenRailwayMap.org">OpenRailwayMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
|
||
|
}
|
||
|
},
|
||
|
OpenFireMap: {
|
||
|
url: 'http://openfiremap.org/hytiles/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 19,
|
||
|
attribution: 'Map data: {attribution.OpenStreetMap} | Map style: © <a href="http://www.openfiremap.org">OpenFireMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
|
||
|
}
|
||
|
},
|
||
|
SafeCast: {
|
||
|
url: 'https://s3.amazonaws.com/te512.safecast.org/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 16,
|
||
|
attribution: 'Map data: {attribution.OpenStreetMap} | Map style: © <a href="https://blog.safecast.org/about/">SafeCast</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
|
||
|
}
|
||
|
},
|
||
|
Stadia: {
|
||
|
url: 'https://tiles.stadiamaps.com/tiles/{variant}/{z}/{x}/{y}{r}.{ext}',
|
||
|
options: {
|
||
|
minZoom: 0,
|
||
|
maxZoom: 20,
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'alidade_smooth',
|
||
|
ext: 'png'
|
||
|
},
|
||
|
variants: {
|
||
|
AlidadeSmooth: 'alidade_smooth',
|
||
|
AlidadeSmoothDark: 'alidade_smooth_dark',
|
||
|
OSMBright: 'osm_bright',
|
||
|
Outdoors: 'outdoors',
|
||
|
StamenToner: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_toner'
|
||
|
}
|
||
|
},
|
||
|
StamenTonerBackground: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_toner_background'
|
||
|
}
|
||
|
},
|
||
|
StamenTonerLines: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_toner_lines'
|
||
|
}
|
||
|
},
|
||
|
StamenTonerLabels: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_toner_labels'
|
||
|
}
|
||
|
},
|
||
|
StamenTonerLite: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_toner_lite'
|
||
|
}
|
||
|
},
|
||
|
StamenWatercolor: {
|
||
|
url: 'https://tiles.stadiamaps.com/tiles/{variant}/{z}/{x}/{y}.{ext}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_watercolor',
|
||
|
ext: 'jpg',
|
||
|
minZoom: 1,
|
||
|
maxZoom: 16
|
||
|
}
|
||
|
},
|
||
|
StamenTerrain: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_terrain',
|
||
|
minZoom: 0,
|
||
|
maxZoom: 18
|
||
|
}
|
||
|
},
|
||
|
StamenTerrainBackground: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_terrain_background',
|
||
|
minZoom: 0,
|
||
|
maxZoom: 18
|
||
|
}
|
||
|
},
|
||
|
StamenTerrainLabels: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_terrain_labels',
|
||
|
minZoom: 0,
|
||
|
maxZoom: 18
|
||
|
}
|
||
|
},
|
||
|
StamenTerrainLines: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.stadiamaps.com/" target="_blank">Stadia Maps</a> ' +
|
||
|
'© <a href="https://www.stamen.com/" target="_blank">Stamen Design</a> ' +
|
||
|
'© <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
variant: 'stamen_terrain_lines',
|
||
|
minZoom: 0,
|
||
|
maxZoom: 18
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
Thunderforest: {
|
||
|
url: 'https://{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png?apikey={apikey}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="http://www.thunderforest.com/">Thunderforest</a>, {attribution.OpenStreetMap}',
|
||
|
variant: 'cycle',
|
||
|
apikey: '<insert your api key here>',
|
||
|
maxZoom: 22
|
||
|
},
|
||
|
variants: {
|
||
|
OpenCycleMap: 'cycle',
|
||
|
Transport: {
|
||
|
options: {
|
||
|
variant: 'transport'
|
||
|
}
|
||
|
},
|
||
|
TransportDark: {
|
||
|
options: {
|
||
|
variant: 'transport-dark'
|
||
|
}
|
||
|
},
|
||
|
SpinalMap: {
|
||
|
options: {
|
||
|
variant: 'spinal-map'
|
||
|
}
|
||
|
},
|
||
|
Landscape: 'landscape',
|
||
|
Outdoors: 'outdoors',
|
||
|
Pioneer: 'pioneer',
|
||
|
MobileAtlas: 'mobile-atlas',
|
||
|
Neighbourhood: 'neighbourhood'
|
||
|
}
|
||
|
},
|
||
|
CyclOSM: {
|
||
|
url: 'https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 20,
|
||
|
attribution: '<a href="https://github.com/cyclosm/cyclosm-cartocss-style/releases" title="CyclOSM - Open Bicycle render">CyclOSM</a> | Map data: {attribution.OpenStreetMap}'
|
||
|
}
|
||
|
},
|
||
|
Jawg: {
|
||
|
url: 'https://{s}.tile.jawg.io/{variant}/{z}/{x}/{y}{r}.png?access-token={accessToken}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'<a href="http://jawg.io" title="Tiles Courtesy of Jawg Maps" target="_blank">© <b>Jawg</b>Maps</a> ' +
|
||
|
'{attribution.OpenStreetMap}',
|
||
|
minZoom: 0,
|
||
|
maxZoom: 22,
|
||
|
subdomains: 'abcd',
|
||
|
variant: 'jawg-terrain',
|
||
|
// Get your own Jawg access token here : https://www.jawg.io/lab/
|
||
|
// NB : this is a demonstration key that comes with no guarantee
|
||
|
accessToken: '<insert your access token here>',
|
||
|
},
|
||
|
variants: {
|
||
|
Streets: 'jawg-streets',
|
||
|
Terrain: 'jawg-terrain',
|
||
|
Sunny: 'jawg-sunny',
|
||
|
Dark: 'jawg-dark',
|
||
|
Light: 'jawg-light',
|
||
|
Matrix: 'jawg-matrix'
|
||
|
}
|
||
|
},
|
||
|
MapBox: {
|
||
|
url: 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}{r}?access_token={accessToken}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'© <a href="https://www.mapbox.com/about/maps/" target="_blank">Mapbox</a> ' +
|
||
|
'{attribution.OpenStreetMap} ' +
|
||
|
'<a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a>',
|
||
|
tileSize: 512,
|
||
|
maxZoom: 18,
|
||
|
zoomOffset: -1,
|
||
|
id: 'mapbox/streets-v11',
|
||
|
accessToken: '<insert your access token here>',
|
||
|
}
|
||
|
},
|
||
|
MapTiler: {
|
||
|
url: 'https://api.maptiler.com/maps/{variant}/{z}/{x}/{y}{r}.{ext}?key={key}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>',
|
||
|
variant: 'streets',
|
||
|
ext: 'png',
|
||
|
key: '<insert your MapTiler Cloud API key here>',
|
||
|
tileSize: 512,
|
||
|
zoomOffset: -1,
|
||
|
minZoom: 0,
|
||
|
maxZoom: 21
|
||
|
},
|
||
|
variants: {
|
||
|
Streets: 'streets',
|
||
|
Basic: 'basic',
|
||
|
Bright: 'bright',
|
||
|
Pastel: 'pastel',
|
||
|
Positron: 'positron',
|
||
|
Hybrid: {
|
||
|
options: {
|
||
|
variant: 'hybrid',
|
||
|
ext: 'jpg'
|
||
|
}
|
||
|
},
|
||
|
Toner: 'toner',
|
||
|
Topo: 'topo',
|
||
|
Voyager: 'voyager'
|
||
|
}
|
||
|
},
|
||
|
TomTom: {
|
||
|
url: 'https://{s}.api.tomtom.com/map/1/tile/{variant}/{style}/{z}/{x}/{y}.{ext}?key={apikey}',
|
||
|
options: {
|
||
|
variant: 'basic',
|
||
|
maxZoom: 22,
|
||
|
attribution:
|
||
|
'<a href="https://tomtom.com" target="_blank">© 1992 - ' + new Date().getFullYear() + ' TomTom.</a> ',
|
||
|
subdomains: 'abcd',
|
||
|
style: 'main',
|
||
|
ext: 'png',
|
||
|
apikey: '<insert your API key here>',
|
||
|
},
|
||
|
variants: {
|
||
|
Basic: 'basic',
|
||
|
Hybrid: 'hybrid',
|
||
|
Labels: 'labels'
|
||
|
}
|
||
|
},
|
||
|
Esri: {
|
||
|
url: 'https://server.arcgisonline.com/ArcGIS/rest/services/{variant}/MapServer/tile/{z}/{y}/{x}',
|
||
|
options: {
|
||
|
variant: 'World_Street_Map',
|
||
|
attribution: 'Tiles © Esri'
|
||
|
},
|
||
|
variants: {
|
||
|
WorldStreetMap: {
|
||
|
options: {
|
||
|
attribution:
|
||
|
'{attribution.Esri} — ' +
|
||
|
'Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012'
|
||
|
}
|
||
|
},
|
||
|
DeLorme: {
|
||
|
options: {
|
||
|
variant: 'Specialty/DeLorme_World_Base_Map',
|
||
|
minZoom: 1,
|
||
|
maxZoom: 11,
|
||
|
attribution: '{attribution.Esri} — Copyright: ©2012 DeLorme'
|
||
|
}
|
||
|
},
|
||
|
WorldTopoMap: {
|
||
|
options: {
|
||
|
variant: 'World_Topo_Map',
|
||
|
attribution:
|
||
|
'{attribution.Esri} — ' +
|
||
|
'Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community'
|
||
|
}
|
||
|
},
|
||
|
WorldImagery: {
|
||
|
options: {
|
||
|
variant: 'World_Imagery',
|
||
|
attribution:
|
||
|
'{attribution.Esri} — ' +
|
||
|
'Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
||
|
}
|
||
|
},
|
||
|
WorldTerrain: {
|
||
|
options: {
|
||
|
variant: 'World_Terrain_Base',
|
||
|
maxZoom: 13,
|
||
|
attribution:
|
||
|
'{attribution.Esri} — ' +
|
||
|
'Source: USGS, Esri, TANA, DeLorme, and NPS'
|
||
|
}
|
||
|
},
|
||
|
WorldShadedRelief: {
|
||
|
options: {
|
||
|
variant: 'World_Shaded_Relief',
|
||
|
maxZoom: 13,
|
||
|
attribution: '{attribution.Esri} — Source: Esri'
|
||
|
}
|
||
|
},
|
||
|
WorldPhysical: {
|
||
|
options: {
|
||
|
variant: 'World_Physical_Map',
|
||
|
maxZoom: 8,
|
||
|
attribution: '{attribution.Esri} — Source: US National Park Service'
|
||
|
}
|
||
|
},
|
||
|
OceanBasemap: {
|
||
|
options: {
|
||
|
variant: 'Ocean/World_Ocean_Base',
|
||
|
maxZoom: 13,
|
||
|
attribution: '{attribution.Esri} — Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri'
|
||
|
}
|
||
|
},
|
||
|
NatGeoWorldMap: {
|
||
|
options: {
|
||
|
variant: 'NatGeo_World_Map',
|
||
|
maxZoom: 16,
|
||
|
attribution: '{attribution.Esri} — National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC'
|
||
|
}
|
||
|
},
|
||
|
WorldGrayCanvas: {
|
||
|
options: {
|
||
|
variant: 'Canvas/World_Light_Gray_Base',
|
||
|
maxZoom: 16,
|
||
|
attribution: '{attribution.Esri} — Esri, DeLorme, NAVTEQ'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
OpenWeatherMap: {
|
||
|
url: 'http://{s}.tile.openweathermap.org/map/{variant}/{z}/{x}/{y}.png?appid={apiKey}',
|
||
|
options: {
|
||
|
maxZoom: 19,
|
||
|
attribution: 'Map data © <a href="http://openweathermap.org">OpenWeatherMap</a>',
|
||
|
apiKey: '<insert your api key here>',
|
||
|
opacity: 0.5
|
||
|
},
|
||
|
variants: {
|
||
|
Clouds: 'clouds',
|
||
|
CloudsClassic: 'clouds_cls',
|
||
|
Precipitation: 'precipitation',
|
||
|
PrecipitationClassic: 'precipitation_cls',
|
||
|
Rain: 'rain',
|
||
|
RainClassic: 'rain_cls',
|
||
|
Pressure: 'pressure',
|
||
|
PressureContour: 'pressure_cntr',
|
||
|
Wind: 'wind',
|
||
|
Temperature: 'temp',
|
||
|
Snow: 'snow'
|
||
|
}
|
||
|
},
|
||
|
HERE: {
|
||
|
/*
|
||
|
* HERE maps, formerly Nokia maps.
|
||
|
* These basemaps are free, but you need an api id and app key. Please sign up at
|
||
|
* https://developer.here.com/plans
|
||
|
*/
|
||
|
url:
|
||
|
'https://{s}.{base}.maps.api.here.com/maptile/2.1/' +
|
||
|
'{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?' +
|
||
|
'app_id={app_id}&app_code={app_code}&lg={language}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'Map © 1987-' + new Date().getFullYear() + ' <a href="http://developer.here.com">HERE</a>',
|
||
|
subdomains: '1234',
|
||
|
mapID: 'newest',
|
||
|
'app_id': '<insert your app_id here>',
|
||
|
'app_code': '<insert your app_code here>',
|
||
|
base: 'base',
|
||
|
variant: 'normal.day',
|
||
|
maxZoom: 20,
|
||
|
type: 'maptile',
|
||
|
language: 'eng',
|
||
|
format: 'png8',
|
||
|
size: '256'
|
||
|
},
|
||
|
variants: {
|
||
|
normalDay: 'normal.day',
|
||
|
normalDayCustom: 'normal.day.custom',
|
||
|
normalDayGrey: 'normal.day.grey',
|
||
|
normalDayMobile: 'normal.day.mobile',
|
||
|
normalDayGreyMobile: 'normal.day.grey.mobile',
|
||
|
normalDayTransit: 'normal.day.transit',
|
||
|
normalDayTransitMobile: 'normal.day.transit.mobile',
|
||
|
normalDayTraffic: {
|
||
|
options: {
|
||
|
variant: 'normal.traffic.day',
|
||
|
base: 'traffic',
|
||
|
type: 'traffictile'
|
||
|
}
|
||
|
},
|
||
|
normalNight: 'normal.night',
|
||
|
normalNightMobile: 'normal.night.mobile',
|
||
|
normalNightGrey: 'normal.night.grey',
|
||
|
normalNightGreyMobile: 'normal.night.grey.mobile',
|
||
|
normalNightTransit: 'normal.night.transit',
|
||
|
normalNightTransitMobile: 'normal.night.transit.mobile',
|
||
|
reducedDay: 'reduced.day',
|
||
|
reducedNight: 'reduced.night',
|
||
|
basicMap: {
|
||
|
options: {
|
||
|
type: 'basetile'
|
||
|
}
|
||
|
},
|
||
|
mapLabels: {
|
||
|
options: {
|
||
|
type: 'labeltile',
|
||
|
format: 'png'
|
||
|
}
|
||
|
},
|
||
|
trafficFlow: {
|
||
|
options: {
|
||
|
base: 'traffic',
|
||
|
type: 'flowtile'
|
||
|
}
|
||
|
},
|
||
|
carnavDayGrey: 'carnav.day.grey',
|
||
|
hybridDay: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.day'
|
||
|
}
|
||
|
},
|
||
|
hybridDayMobile: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.day.mobile'
|
||
|
}
|
||
|
},
|
||
|
hybridDayTransit: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.day.transit'
|
||
|
}
|
||
|
},
|
||
|
hybridDayGrey: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.grey.day'
|
||
|
}
|
||
|
},
|
||
|
hybridDayTraffic: {
|
||
|
options: {
|
||
|
variant: 'hybrid.traffic.day',
|
||
|
base: 'traffic',
|
||
|
type: 'traffictile'
|
||
|
}
|
||
|
},
|
||
|
pedestrianDay: 'pedestrian.day',
|
||
|
pedestrianNight: 'pedestrian.night',
|
||
|
satelliteDay: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'satellite.day'
|
||
|
}
|
||
|
},
|
||
|
terrainDay: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'terrain.day'
|
||
|
}
|
||
|
},
|
||
|
terrainDayMobile: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'terrain.day.mobile'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
HEREv3: {
|
||
|
/*
|
||
|
* HERE maps API Version 3.
|
||
|
* These basemaps are free, but you need an API key. Please sign up at
|
||
|
* https://developer.here.com/plans
|
||
|
* Version 3 deprecates the app_id and app_code access in favor of apiKey
|
||
|
*
|
||
|
* Supported access methods as of 2019/12/21:
|
||
|
* @see https://developer.here.com/faqs#access-control-1--how-do-you-control-access-to-here-location-services
|
||
|
*/
|
||
|
url:
|
||
|
'https://{s}.{base}.maps.ls.hereapi.com/maptile/2.1/' +
|
||
|
'{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?' +
|
||
|
'apiKey={apiKey}&lg={language}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'Map © 1987-' + new Date().getFullYear() + ' <a href="http://developer.here.com">HERE</a>',
|
||
|
subdomains: '1234',
|
||
|
mapID: 'newest',
|
||
|
apiKey: '<insert your apiKey here>',
|
||
|
base: 'base',
|
||
|
variant: 'normal.day',
|
||
|
maxZoom: 20,
|
||
|
type: 'maptile',
|
||
|
language: 'eng',
|
||
|
format: 'png8',
|
||
|
size: '256'
|
||
|
},
|
||
|
variants: {
|
||
|
normalDay: 'normal.day',
|
||
|
normalDayCustom: 'normal.day.custom',
|
||
|
normalDayGrey: 'normal.day.grey',
|
||
|
normalDayMobile: 'normal.day.mobile',
|
||
|
normalDayGreyMobile: 'normal.day.grey.mobile',
|
||
|
normalDayTransit: 'normal.day.transit',
|
||
|
normalDayTransitMobile: 'normal.day.transit.mobile',
|
||
|
normalNight: 'normal.night',
|
||
|
normalNightMobile: 'normal.night.mobile',
|
||
|
normalNightGrey: 'normal.night.grey',
|
||
|
normalNightGreyMobile: 'normal.night.grey.mobile',
|
||
|
normalNightTransit: 'normal.night.transit',
|
||
|
normalNightTransitMobile: 'normal.night.transit.mobile',
|
||
|
reducedDay: 'reduced.day',
|
||
|
reducedNight: 'reduced.night',
|
||
|
basicMap: {
|
||
|
options: {
|
||
|
type: 'basetile'
|
||
|
}
|
||
|
},
|
||
|
mapLabels: {
|
||
|
options: {
|
||
|
type: 'labeltile',
|
||
|
format: 'png'
|
||
|
}
|
||
|
},
|
||
|
trafficFlow: {
|
||
|
options: {
|
||
|
base: 'traffic',
|
||
|
type: 'flowtile'
|
||
|
}
|
||
|
},
|
||
|
carnavDayGrey: 'carnav.day.grey',
|
||
|
hybridDay: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.day'
|
||
|
}
|
||
|
},
|
||
|
hybridDayMobile: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.day.mobile'
|
||
|
}
|
||
|
},
|
||
|
hybridDayTransit: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.day.transit'
|
||
|
}
|
||
|
},
|
||
|
hybridDayGrey: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'hybrid.grey.day'
|
||
|
}
|
||
|
},
|
||
|
pedestrianDay: 'pedestrian.day',
|
||
|
pedestrianNight: 'pedestrian.night',
|
||
|
satelliteDay: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'satellite.day'
|
||
|
}
|
||
|
},
|
||
|
terrainDay: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'terrain.day'
|
||
|
}
|
||
|
},
|
||
|
terrainDayMobile: {
|
||
|
options: {
|
||
|
base: 'aerial',
|
||
|
variant: 'terrain.day.mobile'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
FreeMapSK: {
|
||
|
url: 'https://{s}.freemap.sk/T/{z}/{x}/{y}.jpeg',
|
||
|
options: {
|
||
|
minZoom: 8,
|
||
|
maxZoom: 16,
|
||
|
subdomains: 'abcd',
|
||
|
bounds: [[47.204642, 15.996093], [49.830896, 22.576904]],
|
||
|
attribution:
|
||
|
'{attribution.OpenStreetMap}, visualization CC-By-SA 2.0 <a href="http://freemap.sk">Freemap.sk</a>'
|
||
|
}
|
||
|
},
|
||
|
MtbMap: {
|
||
|
url: 'http://tile.mtbmap.cz/mtbmap_tiles/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'{attribution.OpenStreetMap} & USGS'
|
||
|
}
|
||
|
},
|
||
|
CartoDB: {
|
||
|
url: 'https://{s}.basemaps.cartocdn.com/{variant}/{z}/{x}/{y}{r}.png',
|
||
|
options: {
|
||
|
attribution: '{attribution.OpenStreetMap} © <a href="https://carto.com/attributions">CARTO</a>',
|
||
|
subdomains: 'abcd',
|
||
|
maxZoom: 20,
|
||
|
variant: 'light_all'
|
||
|
},
|
||
|
variants: {
|
||
|
Positron: 'light_all',
|
||
|
PositronNoLabels: 'light_nolabels',
|
||
|
PositronOnlyLabels: 'light_only_labels',
|
||
|
DarkMatter: 'dark_all',
|
||
|
DarkMatterNoLabels: 'dark_nolabels',
|
||
|
DarkMatterOnlyLabels: 'dark_only_labels',
|
||
|
Voyager: 'rastertiles/voyager',
|
||
|
VoyagerNoLabels: 'rastertiles/voyager_nolabels',
|
||
|
VoyagerOnlyLabels: 'rastertiles/voyager_only_labels',
|
||
|
VoyagerLabelsUnder: 'rastertiles/voyager_labels_under'
|
||
|
}
|
||
|
},
|
||
|
HikeBike: {
|
||
|
url: 'https://tiles.wmflabs.org/{variant}/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 19,
|
||
|
attribution: '{attribution.OpenStreetMap}',
|
||
|
variant: 'hikebike'
|
||
|
},
|
||
|
variants: {
|
||
|
HikeBike: {},
|
||
|
HillShading: {
|
||
|
options: {
|
||
|
maxZoom: 15,
|
||
|
variant: 'hillshading'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
BasemapAT: {
|
||
|
url: 'https://mapsneu.wien.gv.at/basemap/{variant}/{type}/google3857/{z}/{y}/{x}.{format}',
|
||
|
options: {
|
||
|
maxZoom: 19,
|
||
|
attribution: 'Datenquelle: <a href="https://www.basemap.at">basemap.at</a>',
|
||
|
type: 'normal',
|
||
|
format: 'png',
|
||
|
bounds: [[46.358770, 8.782379], [49.037872, 17.189532]],
|
||
|
variant: 'geolandbasemap'
|
||
|
},
|
||
|
variants: {
|
||
|
basemap: {
|
||
|
options: {
|
||
|
maxZoom: 20, // currently only in Vienna
|
||
|
variant: 'geolandbasemap'
|
||
|
}
|
||
|
},
|
||
|
grau: 'bmapgrau',
|
||
|
overlay: 'bmapoverlay',
|
||
|
terrain: {
|
||
|
options: {
|
||
|
variant: 'bmapgelaende',
|
||
|
type: 'grau',
|
||
|
format: 'jpeg'
|
||
|
}
|
||
|
},
|
||
|
surface: {
|
||
|
options: {
|
||
|
variant: 'bmapoberflaeche',
|
||
|
type: 'grau',
|
||
|
format: 'jpeg'
|
||
|
}
|
||
|
},
|
||
|
highdpi: {
|
||
|
options: {
|
||
|
variant: 'bmaphidpi',
|
||
|
format: 'jpeg'
|
||
|
}
|
||
|
},
|
||
|
orthofoto: {
|
||
|
options: {
|
||
|
maxZoom: 20, // currently only in Vienna
|
||
|
variant: 'bmaporthofoto30cm',
|
||
|
format: 'jpeg'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
nlmaps: {
|
||
|
url: 'https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0/{variant}/EPSG:3857/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
minZoom: 6,
|
||
|
maxZoom: 19,
|
||
|
bounds: [[50.5, 3.25], [54, 7.6]],
|
||
|
attribution: 'Kaartgegevens © <a href="https://www.kadaster.nl">Kadaster</a>'
|
||
|
},
|
||
|
variants: {
|
||
|
'standaard': 'standaard',
|
||
|
'pastel': 'pastel',
|
||
|
'grijs': 'grijs',
|
||
|
'water': 'water',
|
||
|
'luchtfoto': {
|
||
|
'url': 'https://service.pdok.nl/hwh/luchtfotorgb/wmts/v1_0/Actueel_ortho25/EPSG:3857/{z}/{x}/{y}.jpeg',
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
NASAGIBS: {
|
||
|
url: 'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/{variant}/default/{time}/{tilematrixset}{maxZoom}/{z}/{y}/{x}.{format}',
|
||
|
options: {
|
||
|
attribution:
|
||
|
'Imagery provided by services from the Global Imagery Browse Services (GIBS), operated by the NASA/GSFC/Earth Science Data and Information System ' +
|
||
|
'(<a href="https://earthdata.nasa.gov">ESDIS</a>) with funding provided by NASA/HQ.',
|
||
|
bounds: [[-85.0511287776, -179.999999975], [85.0511287776, 179.999999975]],
|
||
|
minZoom: 1,
|
||
|
maxZoom: 9,
|
||
|
format: 'jpg',
|
||
|
time: '',
|
||
|
tilematrixset: 'GoogleMapsCompatible_Level'
|
||
|
},
|
||
|
variants: {
|
||
|
ModisTerraTrueColorCR: 'MODIS_Terra_CorrectedReflectance_TrueColor',
|
||
|
ModisTerraBands367CR: 'MODIS_Terra_CorrectedReflectance_Bands367',
|
||
|
ViirsEarthAtNight2012: {
|
||
|
options: {
|
||
|
variant: 'VIIRS_CityLights_2012',
|
||
|
maxZoom: 8
|
||
|
}
|
||
|
},
|
||
|
ModisTerraLSTDay: {
|
||
|
options: {
|
||
|
variant: 'MODIS_Terra_Land_Surface_Temp_Day',
|
||
|
format: 'png',
|
||
|
maxZoom: 7,
|
||
|
opacity: 0.75
|
||
|
}
|
||
|
},
|
||
|
ModisTerraSnowCover: {
|
||
|
options: {
|
||
|
variant: 'MODIS_Terra_NDSI_Snow_Cover',
|
||
|
format: 'png',
|
||
|
maxZoom: 8,
|
||
|
opacity: 0.75
|
||
|
}
|
||
|
},
|
||
|
ModisTerraAOD: {
|
||
|
options: {
|
||
|
variant: 'MODIS_Terra_Aerosol',
|
||
|
format: 'png',
|
||
|
maxZoom: 6,
|
||
|
opacity: 0.75
|
||
|
}
|
||
|
},
|
||
|
ModisTerraChlorophyll: {
|
||
|
options: {
|
||
|
variant: 'MODIS_Terra_Chlorophyll_A',
|
||
|
format: 'png',
|
||
|
maxZoom: 7,
|
||
|
opacity: 0.75
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
NLS: {
|
||
|
// NLS maps are copyright National library of Scotland.
|
||
|
// http://maps.nls.uk/projects/api/index.html
|
||
|
// Please contact NLS for anything other than non-commercial low volume usage
|
||
|
//
|
||
|
// Map sources: Ordnance Survey 1:1m to 1:63K, 1920s-1940s
|
||
|
// z0-9 - 1:1m
|
||
|
// z10-11 - quarter inch (1:253440)
|
||
|
// z12-18 - one inch (1:63360)
|
||
|
url: 'https://nls-{s}.tileserver.com/nls/{z}/{x}/{y}.jpg',
|
||
|
options: {
|
||
|
attribution: '<a href="http://geo.nls.uk/maps/">National Library of Scotland Historic Maps</a>',
|
||
|
bounds: [[49.6, -12], [61.7, 3]],
|
||
|
minZoom: 1,
|
||
|
maxZoom: 18,
|
||
|
subdomains: '0123',
|
||
|
}
|
||
|
},
|
||
|
JusticeMap: {
|
||
|
// Justice Map (http://www.justicemap.org/)
|
||
|
// Visualize race and income data for your community, county and country.
|
||
|
// Includes tools for data journalists, bloggers and community activists.
|
||
|
url: 'https://www.justicemap.org/tile/{size}/{variant}/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
attribution: '<a href="http://www.justicemap.org/terms.php">Justice Map</a>',
|
||
|
// one of 'county', 'tract', 'block'
|
||
|
size: 'county',
|
||
|
// Bounds for USA, including Alaska and Hawaii
|
||
|
bounds: [[14, -180], [72, -56]]
|
||
|
},
|
||
|
variants: {
|
||
|
income: 'income',
|
||
|
americanIndian: 'indian',
|
||
|
asian: 'asian',
|
||
|
black: 'black',
|
||
|
hispanic: 'hispanic',
|
||
|
multi: 'multi',
|
||
|
nonWhite: 'nonwhite',
|
||
|
white: 'white',
|
||
|
plurality: 'plural'
|
||
|
}
|
||
|
},
|
||
|
GeoportailFrance: {
|
||
|
url: 'https://wxs.ign.fr/{apikey}/geoportail/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE={style}&TILEMATRIXSET=PM&FORMAT={format}&LAYER={variant}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}',
|
||
|
options: {
|
||
|
attribution: '<a target="_blank" href="https://www.geoportail.gouv.fr/">Geoportail France</a>',
|
||
|
bounds: [[-75, -180], [81, 180]],
|
||
|
minZoom: 2,
|
||
|
maxZoom: 18,
|
||
|
// Get your own geoportail apikey here : http://professionnels.ign.fr/ign/contrats/
|
||
|
// NB : 'choisirgeoportail' is a demonstration key that comes with no guarantee
|
||
|
apikey: 'choisirgeoportail',
|
||
|
format: 'image/png',
|
||
|
style: 'normal',
|
||
|
variant: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2'
|
||
|
},
|
||
|
variants: {
|
||
|
plan: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2',
|
||
|
parcels: {
|
||
|
options: {
|
||
|
variant: 'CADASTRALPARCELS.PARCELLAIRE_EXPRESS',
|
||
|
style: 'PCI vecteur',
|
||
|
maxZoom: 20
|
||
|
}
|
||
|
},
|
||
|
orthos: {
|
||
|
options: {
|
||
|
maxZoom: 19,
|
||
|
format: 'image/jpeg',
|
||
|
variant: 'ORTHOIMAGERY.ORTHOPHOTOS'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
OneMapSG: {
|
||
|
url: 'https://maps-{s}.onemap.sg/v3/{variant}/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
variant: 'Default',
|
||
|
minZoom: 11,
|
||
|
maxZoom: 18,
|
||
|
bounds: [[1.56073, 104.11475], [1.16, 103.502]],
|
||
|
attribution: '<img src="https://docs.onemap.sg/maps/images/oneMap64-01.png" style="height:20px;width:20px;"/> New OneMap | Map data © contributors, <a href="http://SLA.gov.sg">Singapore Land Authority</a>'
|
||
|
},
|
||
|
variants: {
|
||
|
Default: 'Default',
|
||
|
Night: 'Night',
|
||
|
Original: 'Original',
|
||
|
Grey: 'Grey',
|
||
|
LandLot: 'LandLot'
|
||
|
}
|
||
|
},
|
||
|
USGS: {
|
||
|
url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}',
|
||
|
options: {
|
||
|
maxZoom: 20,
|
||
|
attribution: 'Tiles courtesy of the <a href="https://usgs.gov/">U.S. Geological Survey</a>'
|
||
|
},
|
||
|
variants: {
|
||
|
USTopo: {},
|
||
|
USImagery: {
|
||
|
url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}'
|
||
|
},
|
||
|
USImageryTopo: {
|
||
|
url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/tile/{z}/{y}/{x}'
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
WaymarkedTrails: {
|
||
|
url: 'https://tile.waymarkedtrails.org/{variant}/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
maxZoom: 18,
|
||
|
attribution: 'Map data: {attribution.OpenStreetMap} | Map style: © <a href="https://waymarkedtrails.org">waymarkedtrails.org</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
|
||
|
},
|
||
|
variants: {
|
||
|
hiking: 'hiking',
|
||
|
cycling: 'cycling',
|
||
|
mtb: 'mtb',
|
||
|
slopes: 'slopes',
|
||
|
riding: 'riding',
|
||
|
skating: 'skating'
|
||
|
}
|
||
|
},
|
||
|
OpenAIP: {
|
||
|
url: 'https://{s}.tile.maps.openaip.net/geowebcache/service/tms/1.0.0/openaip_basemap@EPSG%3A900913@png/{z}/{x}/{y}.{ext}',
|
||
|
options: {
|
||
|
attribution: '<a href="https://www.openaip.net/">openAIP Data</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-NC-SA</a>)',
|
||
|
ext: 'png',
|
||
|
minZoom: 4,
|
||
|
maxZoom: 14,
|
||
|
tms: true,
|
||
|
detectRetina: true,
|
||
|
subdomains: '12'
|
||
|
}
|
||
|
},
|
||
|
OpenSnowMap: {
|
||
|
url: 'https://tiles.opensnowmap.org/{variant}/{z}/{x}/{y}.png',
|
||
|
options: {
|
||
|
minZoom: 9,
|
||
|
maxZoom: 18,
|
||
|
attribution: 'Map data: {attribution.OpenStreetMap} & ODbL, © <a href="https://www.opensnowmap.org/iframes/data.html">www.opensnowmap.org</a> <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
|
||
|
},
|
||
|
variants: {
|
||
|
pistes: 'pistes',
|
||
|
}
|
||
|
},
|
||
|
AzureMaps: {
|
||
|
url:
|
||
|
'https://atlas.microsoft.com/map/tile?api-version={apiVersion}'+
|
||
|
'&tilesetId={variant}&x={x}&y={y}&zoom={z}&language={language}'+
|
||
|
'&subscription-key={subscriptionKey}',
|
||
|
options: {
|
||
|
attribution: 'See https://docs.microsoft.com/en-us/rest/api/maps/render-v2/get-map-tile for details.',
|
||
|
apiVersion: '2.0',
|
||
|
variant: 'microsoft.imagery',
|
||
|
subscriptionKey: '<insert your subscription key here>',
|
||
|
language: 'en-US',
|
||
|
},
|
||
|
variants: {
|
||
|
MicrosoftImagery: 'microsoft.imagery',
|
||
|
MicrosoftBaseDarkGrey: 'microsoft.base.darkgrey',
|
||
|
MicrosoftBaseRoad: 'microsoft.base.road',
|
||
|
MicrosoftBaseHybridRoad: 'microsoft.base.hybrid.road',
|
||
|
MicrosoftTerraMain: 'microsoft.terra.main',
|
||
|
MicrosoftWeatherInfraredMain: {
|
||
|
url:
|
||
|
'https://atlas.microsoft.com/map/tile?api-version={apiVersion}'+
|
||
|
'&tilesetId={variant}&x={x}&y={y}&zoom={z}'+
|
||
|
'&timeStamp={timeStamp}&language={language}' +
|
||
|
'&subscription-key={subscriptionKey}',
|
||
|
options: {
|
||
|
timeStamp: '2021-05-08T09:03:00Z',
|
||
|
attribution: 'See https://docs.microsoft.com/en-us/rest/api/maps/render-v2/get-map-tile#uri-parameters for details.',
|
||
|
variant: 'microsoft.weather.infrared.main',
|
||
|
},
|
||
|
},
|
||
|
MicrosoftWeatherRadarMain: {
|
||
|
url:
|
||
|
'https://atlas.microsoft.com/map/tile?api-version={apiVersion}'+
|
||
|
'&tilesetId={variant}&x={x}&y={y}&zoom={z}'+
|
||
|
'&timeStamp={timeStamp}&language={language}' +
|
||
|
'&subscription-key={subscriptionKey}',
|
||
|
options: {
|
||
|
timeStamp: '2021-05-08T09:03:00Z',
|
||
|
attribution: 'See https://docs.microsoft.com/en-us/rest/api/maps/render-v2/get-map-tile#uri-parameters for details.',
|
||
|
variant: 'microsoft.weather.radar.main',
|
||
|
},
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
SwissFederalGeoportal: {
|
||
|
url: 'https://wmts.geo.admin.ch/1.0.0/{variant}/default/current/3857/{z}/{x}/{y}.jpeg',
|
||
|
options: {
|
||
|
attribution: '© <a href="https://www.swisstopo.admin.ch/">swisstopo</a>',
|
||
|
minZoom: 2,
|
||
|
maxZoom: 18,
|
||
|
bounds: [[45.398181, 5.140242], [48.230651, 11.47757]]
|
||
|
},
|
||
|
variants: {
|
||
|
NationalMapColor: 'ch.swisstopo.pixelkarte-farbe',
|
||
|
NationalMapGrey: 'ch.swisstopo.pixelkarte-grau',
|
||
|
SWISSIMAGE: {
|
||
|
options: {
|
||
|
variant: 'ch.swisstopo.swissimage',
|
||
|
maxZoom: 19
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
L.tileLayer.provider = function (provider, options) {
|
||
|
return new L.TileLayer.Provider(provider, options);
|
||
|
};
|
||
|
|
||
|
return L;
|
||
|
}));
|
||
|
</script>
|
||
|
<script>LeafletWidget.methods.addProviderTiles = function(provider, layerId, group, options) {
|
||
|
this.layerManager.addLayer(L.tileLayer.provider(provider, options), "tile", layerId, group);
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
</head>
|
||
|
<body style="background-color: white;">
|
||
|
<div id="htmlwidget_container">
|
||
|
<div class="leaflet html-widget html-fill-item" id="htmlwidget-b9fdc3f37e0e342fa6d0" style="width:100%;height:400px;"></div>
|
||
|
</div>
|
||
|
<script type="application/json" data-for="htmlwidget-b9fdc3f37e0e342fa6d0">{"x":{"options":{"crs":{"crsClass":"L.CRS.EPSG3857","code":null,"proj4def":null,"projectedBounds":null,"options":{}},"preferCanvas":true},"calls":[{"method":"addProviderTiles","args":["Stadia.AlidadeSmooth",null,null,{"errorTileUrl":"","noWrap":false,"detectRetina":false}]},{"method":"addMarkers","args":[[42.72913124,44.27292342,43.52963074,43.01111813,43.07056204,44.94999126,44.94999126,42.58670086,44.7830591,42.97685654,44.01522514,44.17384857,43.9649966,43.96571419,43.9636829,42.69272367,43.37538975,43.022016,45.39706332,43.45809745,43.01194698,42.70700911,42.70700911,42.70700911,42.97945756,44.49998065,42.53550551,44.30938772,44.6061339,44.59716141,44.59716141,42.70709499,43.01468193,43.41649978,43.05391805,44.36307891,44.36307891,44.26045493,44.26045493,44.26045493,44.79945057,44.8020267,44.80328196,44.80327769,45.30182571,45.30197289,45.30381907,44.45520124,44.45520124,44.45520124,43.20797302,43.0824614,44.65274961,45.13389899,45.13693059,44.27001053,44.28615675,44.25927979,44.24728099,44.32572104,44.26850867,44.26525219,45.92680802,43.17643575,44.2528434,44.24184278,44.24184278,42.70744276,42.70744276,42.70744276,42.68546516,43.1135579,43.07379981,46.57114356,46.58494645,44.48863293,43.10211361,45.03437393,45.03001896,45.03001896,43.09002814,44.62925587,44.63145855,42.98421054,42.98421054,43.0765954,44.68517965,44.68529451,44.68529451,43.04717524,44.25815875,42.57314554,43.41381546,42.995379,43.03773622,44.510968,44.96661954,43.88775932,43.88786557,44.52821262,43.10211361,44.20863687,43.02888589,43.4723155,43.4723155,43.47711355,43.09840801,43.82914686,43.01309392,43.01309392,43.01309392,42.93273577,45.41652014,45.39706332,43.14175123,44.62139354,42.90802181,44.59466304,44.5118812,42.99452571,44.57373297,42.97349409,46.81513524,46.81513524,46.81513524,43.18046896,43.46577566,44.50549963,43.46181755,43.46008542,42.85879114,42.85777472,42.85777472,42.74171819,42.74171819,42.50862857,42.50862857,42.51871881,42.90501027,43.16553251,44.49820361,42.5676934,42.5676934,42.5676934,43.97672905,43.97698762,44.22775828,43.81233132,43.00411091,43.05086302,43.91429131,44.43942978,42.88699531,42.52665791,45.65406295,45.65406295,45.65406295,45.65523618,44.92922944,44.4733217,42.56951355,42.56951355,42.56951355,43.14630149,44.29275204,44.29384679,44.29101769,44.29101769,42.89712437,45.10796176,45.09860119,45.10938461,43.04203014,43.04203014,45.65406295,44.73815556,44.74029907,44.74029907,43.13267335,43.12953018,43.12953018,42.63247137,44.85674774,44.85674774,45.0460676,45.0460676,44.94887847,42.60484074,43.02401039,43.80373711,42.57604736,44.76498489,43.29023194,45.1908096,42.64045547,44.17368875,44.18828632,44.17368875,42.55659863,42.60609649,42.60954286,42.55041595,43.05522676,43.07875618,43.0649127,42.85530596,42.49984892,43.76159111,42.51009267,44.52240098,43.16976741,43.16534127,43.05697655,43.11739093,45.45960391,43.13550011,43.02061815,45.45960391,45.45960391,43.12101394,46.66638693,42.70709499,42.61295884,43.02720018,42.9655008,43.07774283,42.67095057,43.016209,44.20744079,46.01649755,46.01649755,43.19572747,44.62843552,44.9511207,44.95051638,44.95051638,43.54260377,43.54260377,43.00197822,43.00541417,45.40261364,45.41881315,45.40261364,45.40261364,43.92113894,43.60461369,43.60223893,43.60223893,42.9404927,43.06870371,42.66623628,42.57314554,43.01194698,42.98929612,43.00034043,43.11774906,42.88096068,43.09069312,43.05583245,42.7162214,43.73904006,43.74059553,43.05173637,42.7113076,42.7113076,44.38703365,43.57341638,43.57549648,43.57341638,42.92400922,43.29780198,42.59456995,43.09555027,45.64320881,43.17960229,43.79322291,43.7480674,43.00340278,42.56739765,43.30024527,44.38656164,44.47162766,44.30938772,43.00965021,44.35439712,44.53029804,44.51303715,42.57723323,43.78138255,45.94711035,46.13378448,43.0418905,45.31372284,45.31372284,45.31978132,44.02819461,44.02393239,44.02819461,44.93483439,44.93505181,44.81673297,42.87253789,43.10000524,44.17675657,43.06649796,45.94711035,44.29416297,43.97481509,45.32840622,44.21469034,45.32840622,45.32840622,45.24
|
||
|
<script type="application/htmlwidget-sizing" data-for="htmlwidget-b9fdc3f37e0e342fa6d0">{"viewer":{"width":"100%","height":400,"padding":0,"fill":true},"browser":{"width":"100%","height":400,"padding":0,"fill":true}}</script>
|
||
|
</body>
|
||
|
</html>
|