240 lines
7.2 KiB
JavaScript
240 lines
7.2 KiB
JavaScript
"use strict";
|
|
|
|
import {MapDriverInterface} from "../Interfaces/MapDriverInterface.ecma.js";
|
|
import {EventModel} from "../Models/EventModel.ecma.js";
|
|
import {Utils} from "../Utils/Utils.ecma.js";
|
|
|
|
/**
|
|
* @typedef {import("../Application/RoutesMaker.ecma.js").RoutesMaker} RoutesMaker
|
|
* @typedef {import("../Models/DotModel.ecma.js").DotModel} DotModel
|
|
*/
|
|
|
|
/**
|
|
* @class
|
|
* @constructor
|
|
* @param {!RoutesMaker} routes_maker
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
|
|
* @returns {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
export const LeafLetOSMDriver = (function(){
|
|
|
|
/**
|
|
* @constructs LeafLetOSMDriver
|
|
* @param {!RoutesMaker} routes_maker
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
|
|
* @returns {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
const LeafLetOSMDriver = function(routes_maker, inputs = null){
|
|
|
|
/** @type {LeafLetOSMDriver} */
|
|
const self = this;
|
|
|
|
/** @type {L.Map} */
|
|
this.map = null;
|
|
/** @type {HTMLElement} */
|
|
this.box = null;
|
|
|
|
/** @type {EventModel} */
|
|
this.on_click = new EventModel();
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const constructor = () => {
|
|
MapDriverInterface.check(self);
|
|
};
|
|
|
|
/**
|
|
* @param {!HTMLElement} box
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.build = box => {
|
|
|
|
/** @type {string} */
|
|
let id;
|
|
|
|
if(box.hasAttribute("id"))
|
|
id = box.getAttribute("id");
|
|
else
|
|
box.setAttribute("id", id = routes_maker.random_keys.get());
|
|
|
|
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
|
maxZoom : 19,
|
|
attribution : '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
|
}).addTo(self.map = L.map(id).setView(routes_maker.get_user_coordenates(), 13));
|
|
routes_maker.base.on_change.add(_ => {
|
|
self.map.invalidateSize(true);
|
|
});
|
|
self.map.on("click", event => {
|
|
self.on_click.execute(event.latlng.lng, event.latlng.lat);
|
|
});
|
|
|
|
};
|
|
|
|
const set_value = (object, dom, name, value) => {
|
|
object[dom] && object[dom].setAttribute(name, value);
|
|
};
|
|
|
|
const update_object_attributes = (item, object) => {
|
|
for(const key in item.attributes){
|
|
|
|
/** @type {string} */
|
|
const name = "data-" + Utils.to_kebab(key);
|
|
|
|
["_path", "_icon", "_shadow"].forEach(dom => {
|
|
set_value(object, dom, name, item.attributes[key]);
|
|
});
|
|
|
|
};
|
|
}
|
|
|
|
const set_attributes = (item, object) => {
|
|
object.on("add", () => {
|
|
update_object_attributes(item, object);
|
|
});
|
|
update_object_attributes(item, object);
|
|
};
|
|
|
|
this.update_attributes = item => {
|
|
["marker", "line"].forEach(key => {
|
|
item[key] && update_object_attributes(item, item[key]);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @param {!DotModel} dot
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.add_dot = (dot, attributes = {}) => {
|
|
|
|
/** @type {[number, number]} */
|
|
const point = dot.get_point();
|
|
|
|
(dot.marker = L.marker(point, {draggable : true})).addTo(self.map);
|
|
self.redraw_dot_lines(dot);
|
|
|
|
dot.marker.on("click", event => {
|
|
dot.on_click.execute();
|
|
});
|
|
dot.marker.on("dragend", event => {
|
|
|
|
/** @type {L.LatLng} */
|
|
const coordenates = event.target.getLatLng();
|
|
|
|
dot.on_drop.execute(coordenates.lng, coordenates.lat);
|
|
|
|
});
|
|
set_attributes(dot, dot.marker);
|
|
|
|
};
|
|
|
|
/**
|
|
* @param {!DotModel} dot
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.remove_dot_line = dot => {
|
|
if(dot.line){
|
|
self.map.removeLayer(dot.line);
|
|
dot.line = null;
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @param {!DotModel} dot
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.remove_dot_lines = dot => {
|
|
dot.i && self.remove_dot_line(dot);
|
|
dot.i + 1 < dot.route.dots.length && self.remove_dot_line(dot.route.dots[dot.i + 1]);
|
|
};
|
|
|
|
/**
|
|
* @param {!DotModel} dot
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.redraw_dot_lines = dot => {
|
|
|
|
/** @type {[number, number]} */
|
|
const point = dot.get_point(),
|
|
/** @type {DotModel|null} */
|
|
previous = dot.i ? dot.route.dots[dot.i - 1] : null,
|
|
/** @type {DotModel|null} */
|
|
next = dot.i + 1 < dot.route.dots.length ? dot.route.dots[dot.i + 1] : null;
|
|
|
|
self.remove_dot_lines(dot);
|
|
if(previous){
|
|
(dot.line = L.polyline([previous.get_point(), point])).addTo(self.map);
|
|
set_attributes(dot, dot.line);
|
|
};
|
|
if(next){
|
|
(next.line = L.polyline([point, next.get_point()])).addTo(self.map);
|
|
set_attributes(dot, next.line);
|
|
};
|
|
|
|
};
|
|
|
|
/**
|
|
* @param {!DotModel} dot
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.remove_dot = dot => {
|
|
self.remove_dot_lines(dot);
|
|
self.map.removeLayer(dot.marker);
|
|
};
|
|
|
|
this.create_overlay = overlay => {
|
|
|
|
const item = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
|
|
item.innerHTML = overlay.data.replace(/<\/?svg([^>]*)>/gi, (_, data) => {
|
|
data.matchAll(/ ([^= ]+)="([^"]*)"/g).forEach(([_, key, value]) => {
|
|
item.setAttribute(key, value);
|
|
});
|
|
return "";
|
|
}).replace(/(<([^ >]+) [^\/>]+) \/>/g, "$1></$2>");
|
|
|
|
(overlay.item = L.svgOverlay(item, L.latLngBounds(overlay.position.get_point(), overlay.size.get_point()))).addTo(self.map);
|
|
(overlay.from = L.marker(overlay.position.get_point(), {draggable : true})).addTo(self.map);
|
|
(overlay.to = L.marker(overlay.size.get_point(), {draggable : true})).addTo(self.map);
|
|
|
|
overlay.from.on("dragend", event => {
|
|
|
|
/** @type {L.LatLng} */
|
|
const coordenates = event.target.getLatLng();
|
|
|
|
overlay.on_change_position.execute(coordenates.lng, coordenates.lat);
|
|
|
|
});
|
|
|
|
overlay.to.on("dragend", event => {
|
|
|
|
/** @type {L.LatLng} */
|
|
const coordenates = event.target.getLatLng();
|
|
|
|
overlay.on_change_size.execute(coordenates.lng, coordenates.lat);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
this.update_overalay = overlay => {
|
|
overlay.item.setBounds(L.latLngBounds(overlay.position.get_point(), overlay.size.get_point()));
|
|
};
|
|
|
|
constructor();
|
|
|
|
};
|
|
|
|
return LeafLetOSMDriver;
|
|
})(); |