683 lines
24 KiB
HTML
683 lines
24 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<!--suppress JSVoidFunctionReturnValueUsed -->
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="UTF-8">
|
||
|
<title>Simple Map Paint</title>
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css">
|
||
|
<!-- <script>L_NO_TOUCH = true;</script>-->
|
||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||
|
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||
|
crossorigin=""/>
|
||
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
|
||
|
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
|
||
|
crossorigin=""></script>
|
||
|
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
|
||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/gokertanrisever/leaflet-ruler@master/src/leaflet-ruler.css"
|
||
|
crossorigin="anonymous">
|
||
|
<script src="https://cdn.jsdelivr.net/gh/gokertanrisever/leaflet-ruler@master/src/leaflet-ruler.js"
|
||
|
crossorigin="anonymous"></script>
|
||
|
<script src="https://unpkg.com/leaflet-auto-graticule@1.1.2/dist/L.AutoGraticule.js"></script>
|
||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.min.css"
|
||
|
integrity="sha512-qm+jY0iQ4Xf5RL79UB75REDLYD0jtvxxVZp2RVIW8sm8RNiHdeN43oksqUPrBIshJtQcVPrAL08ML2Db8fFZiA=="
|
||
|
crossorigin="anonymous" referrerpolicy="no-referrer"/>
|
||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.js"
|
||
|
integrity="sha512-ceQPs2CHke3gSINLt/JV37W1rfJOM64yuH999hnRhTP7tNtcSBp5hlTKhn8CEIhsFweSBrZMPVotAKjoyxGWNg=="
|
||
|
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||
|
|
||
|
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet-extra-markers/1.2.2/css/leaflet.extra-markers.min.css" integrity="sha512-wurszDyO1nj6ESdfrXb9h1hmoHMu3sQ3iXgKcu/p81lT+KaPGkta9NIPX7k6XXGgVYpcRHcc8AA4UIeQ7Ax/Cw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-extra-markers/1.2.2/js/leaflet.extra-markers.min.js" integrity="sha512-gGvL9Bo9cO1AY2+HRK8q4+d9yvy7z7dHhLL2YRFdoV7xZSP8wtGZltrmNDvBzIiwaBsybPmg5od7X6BlZh4kKg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||
|
<script src="/Leaflet.EdgeMarker.js"></script>-->
|
||
|
|
||
|
<script src="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js"></script>
|
||
|
<style>
|
||
|
body {
|
||
|
margin: 0;
|
||
|
touch-action: none;
|
||
|
font-family: Arial, Helvetica, sans-serif;
|
||
|
}
|
||
|
|
||
|
#placeholder {
|
||
|
position: absolute;
|
||
|
width: 100vw;
|
||
|
height: 100vh;
|
||
|
background-color: #a4a4a4;
|
||
|
color: black;
|
||
|
font-size: 16px;
|
||
|
font-family: monospace;
|
||
|
z-index: 99999;
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
flex-direction: column;
|
||
|
}
|
||
|
|
||
|
#map {
|
||
|
position: absolute;
|
||
|
top: 0px;
|
||
|
bottom: 0px;
|
||
|
|
||
|
left: 0px;
|
||
|
right: 0px;
|
||
|
height: 100vh;
|
||
|
touch-action: none;
|
||
|
width: 100vw;
|
||
|
}
|
||
|
|
||
|
#log {
|
||
|
position: absolute;
|
||
|
width: 870px;
|
||
|
color: #fafafa;
|
||
|
right: 0;
|
||
|
font-family: monospace;
|
||
|
background-color: rgba(0, 0, 0, 0.5);
|
||
|
/*display: none;*/
|
||
|
z-index: 99999;
|
||
|
}
|
||
|
|
||
|
#users {
|
||
|
position: absolute;
|
||
|
width: 100vw;
|
||
|
color: #fafafa;
|
||
|
bottom: 0;
|
||
|
vertical-align: middle;
|
||
|
font-family: monospace;
|
||
|
background-color: rgba(0, 0, 0, 0.5);
|
||
|
/*display: none;*/
|
||
|
z-index: 99999;
|
||
|
line-height: 26px;
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
font-size: 20px;
|
||
|
}
|
||
|
|
||
|
#hint {
|
||
|
position: absolute;
|
||
|
width: 200px;
|
||
|
color: #fafafa;
|
||
|
top: 0;
|
||
|
left: 50px;
|
||
|
vertical-align: middle;
|
||
|
font-family: monospace;
|
||
|
background-color: rgba(0, 0, 0, 0.5);
|
||
|
/*display: none;*/
|
||
|
z-index: 99999;
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
font-size: 11px;
|
||
|
}
|
||
|
</style>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div id="placeholder">
|
||
|
loading...
|
||
|
</div>
|
||
|
<div id="users">
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<div id="hint">
|
||
|
* Space - toggle drawing <br>
|
||
|
* 10m save for 500 last lines
|
||
|
</div>
|
||
|
|
||
|
<div id="map">
|
||
|
|
||
|
</div>
|
||
|
<script>
|
||
|
var notyf = new Notyf({
|
||
|
duration: 1000,
|
||
|
position: {
|
||
|
x: 'center',
|
||
|
y: 'bottom',
|
||
|
},
|
||
|
types: [
|
||
|
{
|
||
|
type: 'success',
|
||
|
background: 'green',
|
||
|
dismissible: false,
|
||
|
},
|
||
|
{
|
||
|
type: 'error',
|
||
|
background: 'indianred',
|
||
|
duration: 2000,
|
||
|
dismissible: false
|
||
|
},
|
||
|
{
|
||
|
type: 'info',
|
||
|
icon: {
|
||
|
className: 'notyf__icon--success',
|
||
|
tagName: 'i',
|
||
|
},
|
||
|
background: '#0096f6',
|
||
|
duration: 2000,
|
||
|
dismissible: false
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
var socket = io();
|
||
|
var randomColor;
|
||
|
var myId = 0;
|
||
|
const userDiv = document.getElementById('users');
|
||
|
|
||
|
L.Map.mergeOptions({
|
||
|
touchExtend: true
|
||
|
});
|
||
|
|
||
|
L.Map.TouchExtend = L.Handler.extend({
|
||
|
|
||
|
// @method initialize(): void
|
||
|
// Sets TouchExtend private accessor variables
|
||
|
initialize: function (map) {
|
||
|
this._map = map;
|
||
|
this._container = map._container;
|
||
|
this._pane = map._panes.overlayPane;
|
||
|
},
|
||
|
|
||
|
// @method addHooks(): void
|
||
|
// Adds dom listener events to the map container
|
||
|
addHooks: function () {
|
||
|
L.DomEvent.on(this._container, 'touchstart', this._onTouchStart, this);
|
||
|
L.DomEvent.on(this._container, 'touchend', this._onTouchEnd, this);
|
||
|
L.DomEvent.on(this._container, 'touchmove', this._onTouchMove, this);
|
||
|
L.DomEvent.on(this._container, 'touchcancel', this._onTouchCancel, this);
|
||
|
L.DomEvent.on(this._container, 'touchleave', this._onTouchLeave, this);
|
||
|
},
|
||
|
|
||
|
// @method removeHooks(): void
|
||
|
// Removes dom listener events from the map container
|
||
|
removeHooks: function () {
|
||
|
L.DomEvent.off(this._container, 'touchstart', this._onTouchStart, this);
|
||
|
L.DomEvent.off(this._container, 'touchend', this._onTouchEnd, this);
|
||
|
L.DomEvent.off(this._container, 'touchmove', this._onTouchMove, this);
|
||
|
L.DomEvent.off(this._container, 'touchcancel', this._onTouchCancel, this);
|
||
|
L.DomEvent.off(this._container, 'touchleave', this._onTouchLeave, this);
|
||
|
},
|
||
|
|
||
|
_touchEvent: function (e, type) {
|
||
|
// #TODO: fix the pageX error that is do a bug in Android where a single touch triggers two click events
|
||
|
// _filterClick is what leaflet uses as a workaround.
|
||
|
// This is a problem with more things than just android. Another problem is touchEnd has no touches in
|
||
|
// its touch list.
|
||
|
var touchEvent = {};
|
||
|
if (typeof e.touches !== 'undefined') {
|
||
|
if (!e.touches.length) {
|
||
|
if (type === 'touchend') {
|
||
|
this._map.fire(type, {
|
||
|
originalEvent: e
|
||
|
});
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
touchEvent = e.touches[0];
|
||
|
} else if (e.pointerType === 'touch') {
|
||
|
touchEvent = e;
|
||
|
if (!this._filterClick(e)) {
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var containerPoint = this._map.mouseEventToContainerPoint(touchEvent),
|
||
|
layerPoint = this._map.mouseEventToLayerPoint(touchEvent),
|
||
|
latlng = this._map.layerPointToLatLng(layerPoint);
|
||
|
|
||
|
this._map.fire(type, {
|
||
|
latlng: latlng,
|
||
|
layerPoint: layerPoint,
|
||
|
containerPoint: containerPoint,
|
||
|
pageX: touchEvent.pageX,
|
||
|
pageY: touchEvent.pageY,
|
||
|
originalEvent: e
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/** Borrowed from Leaflet and modified for bool ops **/
|
||
|
_filterClick: function (e) {
|
||
|
var timeStamp = (e.timeStamp || e.originalEvent.timeStamp),
|
||
|
elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick);
|
||
|
|
||
|
// are they closer together than 500ms yet more than 100ms?
|
||
|
// Android typically triggers them ~300ms apart while multiple listeners
|
||
|
// on the same event should be triggered far faster;
|
||
|
// or check if click is simulated on the element, and if it is, reject any non-simulated events
|
||
|
if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {
|
||
|
L.DomEvent.stop(e);
|
||
|
return false;
|
||
|
}
|
||
|
L.DomEvent._lastClick = timeStamp;
|
||
|
return true;
|
||
|
},
|
||
|
|
||
|
_onTouchStart: function (e) {
|
||
|
if (!this._map._loaded) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var type = 'touchstart';
|
||
|
this._touchEvent(e, type);
|
||
|
|
||
|
},
|
||
|
|
||
|
_onTouchEnd: function (e) {
|
||
|
if (!this._map._loaded) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var type = 'touchend';
|
||
|
this._touchEvent(e, type);
|
||
|
},
|
||
|
|
||
|
_onTouchCancel: function (e) {
|
||
|
if (!this._map._loaded) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var type = 'touchcancel';
|
||
|
if (this._detectIE()) {
|
||
|
type = 'pointercancel';
|
||
|
}
|
||
|
this._touchEvent(e, type);
|
||
|
},
|
||
|
|
||
|
_onTouchLeave: function (e) {
|
||
|
if (!this._map._loaded) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var type = 'touchleave';
|
||
|
this._touchEvent(e, type);
|
||
|
},
|
||
|
|
||
|
_onTouchMove: function (e) {
|
||
|
if (!this._map._loaded) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var type = 'touchmove';
|
||
|
this._touchEvent(e, type);
|
||
|
},
|
||
|
|
||
|
});
|
||
|
|
||
|
L.Map.addInitHook('addHandler', 'touchExtend', L.Map.TouchExtend);
|
||
|
|
||
|
var map = L.map('map', {
|
||
|
dragging: true,
|
||
|
doubleClickZoom: false,
|
||
|
minZoom: 4,
|
||
|
}).setView([48.8659904, 31.3847594], 7);
|
||
|
|
||
|
L.Map.mergeOptions({
|
||
|
touchExtend: true
|
||
|
});
|
||
|
|
||
|
L.control.ruler().addTo(map);
|
||
|
new L.AutoGraticule().addTo(map);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
var Temp = L.tileLayer(
|
||
|
"https://tile.openweathermap.org/map/temp_new/{z}/{x}/{y}.png?appid=d22d9a6a3ff2aa523d5917bbccc89211",
|
||
|
{
|
||
|
maxZoom: 18,
|
||
|
attribution: '© <a href="http://owm.io">VANE</a>',
|
||
|
id: "temp"
|
||
|
}
|
||
|
),
|
||
|
Precipitation = L.tileLayer(
|
||
|
"https://tile.openweathermap.org/map/precipitation_new/{z}/{x}/{y}.png?appid=d22d9a6a3ff2aa523d5917bbccc89211",
|
||
|
{
|
||
|
maxZoom: 18,
|
||
|
attribution: '© <a href="http://owm.io">VANE</a>'
|
||
|
}
|
||
|
),
|
||
|
Wind = L.tileLayer(
|
||
|
"https://tile.openweathermap.org/map/wind_new/{z}/{x}/{y}.png?appid=d22d9a6a3ff2aa523d5917bbccc89211",
|
||
|
{
|
||
|
maxZoom: 18,
|
||
|
attribution: '© <a href="http://owm.io">VANE</a>'
|
||
|
}
|
||
|
),
|
||
|
Pressure = L.tileLayer(
|
||
|
"https://tile.openweathermap.org/map/pressure_new/{z}/{x}/{y}.png?appid=d22d9a6a3ff2aa523d5917bbccc89211",
|
||
|
{
|
||
|
maxZoom: 18,
|
||
|
attribution: '© <a href="http://owm.io">VANE</a>'
|
||
|
}
|
||
|
),
|
||
|
Clouds = L.tileLayer(
|
||
|
"https://tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=d22d9a6a3ff2aa523d5917bbccc89211",
|
||
|
{
|
||
|
maxZoom: 18,
|
||
|
attribution: '© <a href="http://owm.io">VANE</a>'
|
||
|
}
|
||
|
);
|
||
|
|
||
|
|
||
|
//Temp.addTo(map);
|
||
|
|
||
|
const getMapLocation = function (zoom, center) {
|
||
|
'use strict';
|
||
|
zoom = (zoom || zoom === 0) ? zoom : 7;
|
||
|
center = (center) ? center : [48.8659904, 31.3847594];
|
||
|
|
||
|
if (window.location.hash !== '') {
|
||
|
var hash = window.location.hash.replace('#', '');
|
||
|
var parts = hash.split(',');
|
||
|
if (parts.length === 3) {
|
||
|
center = {
|
||
|
lat: parseFloat(parts[0]),
|
||
|
lng: parseFloat(parts[1])
|
||
|
};
|
||
|
zoom = parseInt(parts[2].slice(0, -1), 10);
|
||
|
}
|
||
|
}
|
||
|
return {zoom: zoom, center: center};
|
||
|
}
|
||
|
|
||
|
var hash = getMapLocation();
|
||
|
|
||
|
map.setView(hash.center, hash.zoom);
|
||
|
|
||
|
map.on('moveend', function () {
|
||
|
var center = map.getCenter();
|
||
|
var hash = '#' +
|
||
|
Math.round(center.lat * 100000) / 100000 + ',' +
|
||
|
Math.round(center.lng * 100000) / 100000 + ',' +
|
||
|
map.getZoom() + 'z';
|
||
|
var state = {
|
||
|
zoom: map.getZoom(),
|
||
|
center: center
|
||
|
};
|
||
|
window.history.pushState(state, 'map', hash);
|
||
|
});
|
||
|
|
||
|
var OpenStreetMap_Mapnik = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
|
maxZoom: 19,
|
||
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||
|
});
|
||
|
var OpenTopoMap = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
|
||
|
maxZoom: 17,
|
||
|
attribution: 'Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <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>)'
|
||
|
});
|
||
|
var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
||
|
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
||
|
});
|
||
|
var Stamen_Toner = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}{r}.{ext}', {
|
||
|
attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> — Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||
|
subdomains: 'abcd',
|
||
|
minZoom: 0,
|
||
|
maxZoom: 20,
|
||
|
ext: 'png'
|
||
|
});
|
||
|
OpenStreetMap_Mapnik.addTo(map);
|
||
|
var OpenStreetMap_Mapnik2 = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
|
maxZoom: 19,
|
||
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||
|
});
|
||
|
var miniMap = new L.Control.MiniMap(OpenStreetMap_Mapnik2).addTo(map);
|
||
|
|
||
|
var layerControl = L.control.layers({
|
||
|
"OSM": OpenStreetMap_Mapnik,
|
||
|
"OSM Topo": OpenTopoMap,
|
||
|
"ERSI Sat": Esri_WorldImagery,
|
||
|
"Contrast": Stamen_Toner
|
||
|
}, {
|
||
|
Temperature: Temp,
|
||
|
Precipitation: Precipitation,
|
||
|
Clouds: Clouds,
|
||
|
Pressure: Pressure,
|
||
|
Wind: Wind
|
||
|
}).addTo(map);
|
||
|
|
||
|
var paintMode = false;
|
||
|
var myPolyline;
|
||
|
|
||
|
var dr = false;
|
||
|
|
||
|
var loading = document.getElementById('placeholder');
|
||
|
|
||
|
socket.on('draw', function (msg) {
|
||
|
var polyline = L.polyline(msg.line, {color: msg.color}).addTo(map);
|
||
|
});
|
||
|
|
||
|
loading.innerHTML = "Loading history...";
|
||
|
|
||
|
socket.once('history', function (lines) {
|
||
|
lines.forEach(line => {
|
||
|
var polyline = L.polyline(line.line, {color: line.color}).addTo(map);
|
||
|
})
|
||
|
loading.innerHTML = "History loaded...";
|
||
|
loading.style.display = 'none';
|
||
|
});
|
||
|
|
||
|
socket.on('color', function (user) {
|
||
|
randomColor = user.color;
|
||
|
myId = user.id;
|
||
|
loading.innerHTML = "Color generated...";
|
||
|
});
|
||
|
|
||
|
/*var markers = L.layerGroup([]);
|
||
|
markers.addTo(map);
|
||
|
var myMakerIcon;
|
||
|
|
||
|
L.edgeMarker({
|
||
|
icon: L.icon({ // style markers
|
||
|
iconUrl: 'edge-arrow-marker-black.png',
|
||
|
clickable: true,
|
||
|
iconSize: [48, 48],
|
||
|
iconAnchor: [24, 24]
|
||
|
}),
|
||
|
rotateIcons: true,
|
||
|
layerGroup: markers
|
||
|
}).addTo(map);*/
|
||
|
|
||
|
socket.on('users', function (users) {
|
||
|
userDiv.innerHTML = "";
|
||
|
const currentUserIndex = users.findIndex(user => user.id === myId);
|
||
|
if (currentUserIndex !== -1) {
|
||
|
const currentUser = users.splice(currentUserIndex, 1)[0];
|
||
|
users.sort((a, b) => a.id - b.id);
|
||
|
users.unshift(currentUser);
|
||
|
}
|
||
|
users.forEach((user, index) => {
|
||
|
if (index === 0) {
|
||
|
/*myMakerIcon = L.ExtraMarkers.icon({ //SET MY MARKER ICON
|
||
|
icon: 'fa-number',
|
||
|
svg: true,
|
||
|
markerColor: randomColor,
|
||
|
shape: 'circle',
|
||
|
prefix: ''
|
||
|
});*/
|
||
|
|
||
|
userDiv.innerHTML += 'You: ';
|
||
|
userDiv.innerHTML += `<input type="color" id="you" style="width: 26px; margin-right: 3px; border: 2px solid ${user.color}; height: 26px; border-radius: 50%; display: inline-block" value="${user.color}">`;
|
||
|
// userDiv.innerHTML += `<div id="user-${user.id}" class="${cl}" title="${title}" style="background-color: ${user.color}; width: 20px; margin-right: 3px; height: 20px; border-radius: 50%; display: inline-block"></div>`;
|
||
|
userDiv.innerHTML += 'Others: ';
|
||
|
} else {
|
||
|
notyf.open({
|
||
|
type: 'info',
|
||
|
message: 'User connected'
|
||
|
});
|
||
|
userDiv.innerHTML += `<div id="user-${user.id}" class="other" title="User ${user.id}" style="background-color: ${user.color}; margin-top: 3px; width: 20px; margin-right: 3px; height: 20px; border-radius: 50%; display: inline-block"></div>`;
|
||
|
}
|
||
|
|
||
|
})
|
||
|
loading.innerHTML = "Users ...";
|
||
|
});
|
||
|
|
||
|
|
||
|
/*socket.on('new_marker', function (marker) {
|
||
|
var newMarker = L.marker([marker.coords.lat, marker.coords.lng], {
|
||
|
draggable: true,
|
||
|
autoPan: false,
|
||
|
icon: L.ExtraMarkers.icon({ // style markers
|
||
|
icon: 'fa-number',
|
||
|
svg: true,
|
||
|
markerColor: marker.color,
|
||
|
shape: 'circle',
|
||
|
prefix: ''
|
||
|
})
|
||
|
});
|
||
|
|
||
|
newMarker.addTo(markers);
|
||
|
// newMarker.on("dragend", function () {
|
||
|
// socket.emit('new_marker', {"color": randomColor, "user": myId, "coords": newMarker.getLatLng()});
|
||
|
// });
|
||
|
});*/
|
||
|
|
||
|
|
||
|
var changedColor = false;
|
||
|
|
||
|
userDiv.addEventListener('click', function (event) {
|
||
|
if (event.target.id === 'you') {
|
||
|
const userElement = event.target;
|
||
|
|
||
|
userElement.addEventListener('input', colorChangeEvent => {
|
||
|
const selectedColor = colorChangeEvent.target.value;
|
||
|
randomColor = selectedColor;
|
||
|
changedColor = true;
|
||
|
});
|
||
|
|
||
|
|
||
|
}
|
||
|
});
|
||
|
|
||
|
map.on('mousedown touchstart pointerdown', function (e) {
|
||
|
if ('originalEvent' in e) {
|
||
|
if (e.originalEvent.button === 1) {
|
||
|
map.dragging.enable();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (changedColor === true) {
|
||
|
socket.emit('new_color', {"color": randomColor, "user": myId});
|
||
|
changedColor = false;
|
||
|
}
|
||
|
|
||
|
if (paintMode) {
|
||
|
map.dragging.disable();
|
||
|
myPolyline = L.polyline([], {color: randomColor}).addTo(map);
|
||
|
}
|
||
|
dr = true;
|
||
|
});
|
||
|
map.on('mouseup touchend pointerup touchleave', function (e) {
|
||
|
dr = false;
|
||
|
if (typeof myPolyline !== 'undefined' && null !== myPolyline) {
|
||
|
socket.emit('draw', {"line": myPolyline.getLatLngs(), "user": myId});
|
||
|
}
|
||
|
})
|
||
|
|
||
|
map.on('mousemove touchmove pointermove', function (e) {
|
||
|
// console.log('mousemove')
|
||
|
if (paintMode && dr) {
|
||
|
|
||
|
if (e.type === 'touchmove' && e.originalEvent.touches.length > 1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
myPolyline.addLatLng(e.latlng);
|
||
|
}
|
||
|
})
|
||
|
|
||
|
document.body.onkeyup = function (e) {
|
||
|
if (e.key == " " ||
|
||
|
e.code == "Space" ||
|
||
|
e.keyCode == 32
|
||
|
) {
|
||
|
var container = document.getElementsByClassName('draw-paint')[0];
|
||
|
paintMode = !paintMode;
|
||
|
if (paintMode) {
|
||
|
container.style.backgroundColor = '#bfea90';
|
||
|
map.dragging.disable();
|
||
|
notyf.success("Paint Mode <b>ENABLED</b>");
|
||
|
} else {
|
||
|
container.style.backgroundColor = 'white';
|
||
|
map.dragging.enable();
|
||
|
notyf.success("Paint Mode <b style='color: #ffa6a6'>DISABLED</b>");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var drawPaint = L.Control.extend({
|
||
|
|
||
|
options: {
|
||
|
position: 'topleft'
|
||
|
},
|
||
|
|
||
|
onAdd: function (map) {
|
||
|
var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom draw-paint');
|
||
|
|
||
|
container.style.backgroundColor = 'white';
|
||
|
container.style.backgroundImage = "url(https://assada.dead.guru/storage/images/image_2023_08_16_16_46_52.png)";
|
||
|
container.style.backgroundSize = "30px 30px";
|
||
|
container.style.width = '30px';
|
||
|
container.style.height = '30px';
|
||
|
container.setAttribute('title', "Toggle drawing");
|
||
|
|
||
|
container.onclick = function () {
|
||
|
paintMode = !paintMode;
|
||
|
if (paintMode) {
|
||
|
map.dragging.disable();
|
||
|
container.style.backgroundColor = '#bfea90';
|
||
|
notyf.success("Paint Mode <b>ENABLED</b>");
|
||
|
} else {
|
||
|
map.dragging.enable();
|
||
|
container.style.backgroundColor = 'white';
|
||
|
notyf.success("Paint Mode <b style='color: #ffa6a6'>DISABLED</b>");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return container;
|
||
|
}
|
||
|
});
|
||
|
/*
|
||
|
var drawMarker = L.Control.extend({
|
||
|
|
||
|
options: {
|
||
|
position: 'topleft'
|
||
|
},
|
||
|
|
||
|
onAdd: function (map) {
|
||
|
var container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom draw-paint');
|
||
|
|
||
|
container.style.backgroundColor = 'white';
|
||
|
container.style.backgroundImage = "url(https://assada.dead.guru/storage/images/image_2023_08_16_16_46_52.png)";
|
||
|
container.style.backgroundSize = "30px 30px";
|
||
|
container.style.width = '30px';
|
||
|
container.style.height = '30px';
|
||
|
container.setAttribute('title', "Add marker");
|
||
|
|
||
|
container.onclick = function () {
|
||
|
notyf.success("You can move marker by drag and drop");
|
||
|
|
||
|
var newMarker = L.marker(map.getCenter(), {
|
||
|
draggable: true,
|
||
|
autoPan: false,
|
||
|
icon: myMakerIcon
|
||
|
});
|
||
|
|
||
|
newMarker.addTo(markers);
|
||
|
newMarker.on("dragend", function () {
|
||
|
socket.emit('new_marker', {"color": randomColor, "user": myId, "coords": newMarker.getLatLng()});
|
||
|
});
|
||
|
|
||
|
socket.emit('new_marker', {"color": randomColor, "user": myId, "coords": newMarker.getLatLng()});
|
||
|
}
|
||
|
|
||
|
return container;
|
||
|
}
|
||
|
});*/
|
||
|
|
||
|
map.addControl(new drawPaint());
|
||
|
// map.addControl(new drawMarker());
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|