feature/google-maps-in-mapeditor-added #33

Merged
bence merged 9 commits from feature/google-maps-in-mapeditor-added into develop 2021-05-02 13:38:17 +02:00
10 changed files with 351 additions and 84 deletions

View File

@ -1,4 +1,4 @@
#map { .map {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@ -7,6 +7,13 @@
z-index: 1; z-index: 1;
} }
#mapSelection img {
display: inline;
width: 1em;
height: 1em;
vertical-align: -0.15em;
}
/* modify the cursor for the Leaflet map */ /* modify the cursor for the Leaflet map */
.leaflet-container { .leaflet-container {
cursor: crosshair; cursor: crosshair;
@ -65,6 +72,9 @@
#placeControl { #placeControl {
top: calc(50% + 10px); top: calc(50% + 10px);
} }
.hideOnMobile {
display: none;
}
} }
@media screen and (min-width: 1000px), (max-height: 599px) { @media screen and (min-width: 1000px), (max-height: 599px) {

View File

@ -0,0 +1,4 @@
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
<svg xmlns="http://www.w3.org/2000/svg" fill="#ffffff" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M15.817.113A.5.5 0 0 1 16 .5v14a.5.5 0 0 1-.402.49l-5 1a.502.502 0 0 1-.196 0L5.5 15.01l-4.902.98A.5.5 0 0 1 0 15.5v-14a.5.5 0 0 1 .402-.49l5-1a.5.5 0 0 1 .196 0L10.5.99l4.902-.98a.5.5 0 0 1 .415.103zM10 1.91l-4-.8v12.98l4 .8V1.91zm1 12.98 4-.8V1.11l-4 .8v12.98zm-6-.8V1.11l-4 .8v12.98l4-.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 530 B

BIN
public/static/img/markers/m1.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
public/static/img/markers/m2.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
public/static/img/markers/m3.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
public/static/img/markers/m4.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
public/static/img/markers/m5.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
<!-- Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. -->
<svg xmlns="http://www.w3.org/2000/svg" fill="#ffffff" viewBox="0 0 16 16">
<path d="m14.12 10.163 1.715.858c.22.11.22.424 0 .534L8.267 15.34a.598.598 0 0 1-.534 0L.165 11.555a.299.299 0 0 1 0-.534l1.716-.858 5.317 2.659c.505.252 1.1.252 1.604 0l5.317-2.66zM7.733.063a.598.598 0 0 1 .534 0l7.568 3.784a.3.3 0 0 1 0 .535L8.267 8.165a.598.598 0 0 1-.534 0L.165 4.382a.299.299 0 0 1 0-.535L7.733.063z"/>
<path d="m14.12 6.576 1.715.858c.22.11.22.424 0 .534l-7.568 3.784a.598.598 0 0 1-.534 0L.165 7.968a.299.299 0 0 1 0-.534l1.716-.858 5.317 2.659c.505.252 1.1.252 1.604 0l5.317-2.659z"/>
</svg>

After

Width:  |  Height:  |  Size: 718 B

View File

@ -7,7 +7,6 @@
description: null description: null
}, },
map: null, map: null,
markers: null,
panorama: null, panorama: null,
selectedMarker: null, selectedMarker: null,
added: {}, added: {},
@ -118,16 +117,13 @@
MapEditor.resetSelected(); MapEditor.resetSelected();
MapEditor.selectedMarker = marker; MapEditor.selectedMarker = marker;
MapEditor.map.invalidateSize(true); MapEditor.map.resize();
MapEditor.map.panTo(marker.getLatLng()); MapEditor.map.panTo(marker.getLatLng());
MapEditor.panorama.setVisible(false); MapEditor.panorama.setVisible(false);
if (marker.placeId) { if (marker.placeId) {
MapEditor.markers.removeLayer(MapEditor.selectedMarker); MapEditor.map.changeMarkerIcon(marker, MapEditor.map.iconCollection.iconBlue);
MapEditor.map.addLayer(MapEditor.selectedMarker);
marker.setIcon(IconCollection.iconBlue);
marker.setZIndexOffset(2000);
document.getElementById('deleteButton').style.display = 'block'; document.getElementById('deleteButton').style.display = 'block';
@ -165,13 +161,13 @@
var placeId = MapEditor.selectedMarker.placeId var placeId = MapEditor.selectedMarker.placeId
if (places[placeId].id && !del) { if (places[placeId].id && !del) {
MapEditor.map.removeLayer(MapEditor.selectedMarker); MapEditor.map.changeMarkerIcon(
MapEditor.markers.addLayer(MapEditor.selectedMarker); MapEditor.selectedMarker,
MapEditor.selectedMarker.setIcon(places[placeId].noPano ? IconCollection.iconRed : IconCollection.iconGreen); places[placeId].noPano ? MapEditor.map.iconCollection.iconRed : MapEditor.map.iconCollection.iconGreen
MapEditor.selectedMarker.setZIndexOffset(1000); );
} else { } else {
delete places[placeId]; delete places[placeId];
MapEditor.map.removeLayer(MapEditor.selectedMarker); MapEditor.map.removeMarker(MapEditor.selectedMarker);
} }
document.getElementById('deleteButton').style.display = 'none'; document.getElementById('deleteButton').style.display = 'none';
@ -223,7 +219,7 @@
MapEditor.resetSelected(del); MapEditor.resetSelected(del);
MapEditor.selectedMarker = null; MapEditor.selectedMarker = null;
MapEditor.map.invalidateSize(true); MapEditor.map.resize();
}, },
deletePlace: function () { deletePlace: function () {
@ -239,6 +235,7 @@
delete MapEditor.added[placeId]; delete MapEditor.added[placeId];
delete MapEditor.edited[placeId]; delete MapEditor.edited[placeId];
delete places[placeId];
document.getElementById('added').innerHTML = String(Object.keys(MapEditor.added).length); document.getElementById('added').innerHTML = String(Object.keys(MapEditor.added).length);
document.getElementById('edited').innerHTML = String(Object.keys(MapEditor.edited).length); document.getElementById('edited').innerHTML = String(Object.keys(MapEditor.edited).length);
@ -310,42 +307,9 @@
var placeId = addedPlaces[i].id; var placeId = addedPlaces[i].id;
places[tempId].id = placeId; places[tempId].id = placeId;
} }
},
// TODO: check whether marker is already existing on the map for the coordinates
// or alternatively block saving for matching coordinates
placeMarker: function (latlng) {
var marker = L.marker(latlng, {
icon: IconCollection.iconBlue,
zIndexOffset: 2000
})
.addTo(MapEditor.map)
.on('click', function () {
MapEditor.select(this);
});
MapEditor.select(marker);
} }
}; };
var IconCollection = {
iconGreen: L.icon({
iconUrl: STATIC_ROOT + '/img/markers/marker-green.svg?rev' + REVISION,
iconSize: [24, 32],
iconAnchor: [12, 32]
}),
iconRed: L.icon({
iconUrl: STATIC_ROOT + '/img/markers/marker-red.svg?rev=' + REVISION,
iconSize: [24, 32],
iconAnchor: [12, 32]
}),
iconBlue: L.icon({
iconUrl: STATIC_ROOT + '/img/markers/marker-blue.svg?rev=' + REVISION,
iconSize: [24, 32],
iconAnchor: [12, 32]
}),
};
var Util = { var Util = {
getHighResData: function () { getHighResData: function () {
if (window.devicePixelRatio >= 4) { if (window.devicePixelRatio >= 4) {
@ -384,52 +348,290 @@
} }
}; };
MapEditor.map = L.map('map', { var LMapWrapper = {
zoomControl: false map: null,
}); markers: null,
divId: null,
iconCollection: {
iconGreen: L.icon({
iconUrl: STATIC_ROOT + '/img/markers/marker-green.svg?rev' + REVISION,
iconSize: [24, 32],
iconAnchor: [12, 32]
}),
iconRed: L.icon({
iconUrl: STATIC_ROOT + '/img/markers/marker-red.svg?rev=' + REVISION,
iconSize: [24, 32],
iconAnchor: [12, 32]
}),
iconBlue: L.icon({
iconUrl: STATIC_ROOT + '/img/markers/marker-blue.svg?rev=' + REVISION,
iconSize: [24, 32],
iconAnchor: [12, 32]
})
},
MapEditor.map.on('click', function (e) { init: function (divId, places) {
MapEditor.placeMarker(e.latlng); document.getElementById(divId).style.display = "block";
});
var highResData = Util.getHighResData(); if (!LMapWrapper.map) {
LMapWrapper.divId = divId;
LMapWrapper.map = L.map(LMapWrapper.divId, {
center: { lat: 0., lng: 0. },
zoom: 2,
zoomControl: false
});
L.tileLayer(tileUrl, { LMapWrapper.map.on('click', function (e) {
attribution: tileAttribution, LMapWrapper.placeMarker(e.latlng);
subdomains: '1234', });
ppi: highResData.ppi,
tileSize: highResData.tileSize,
zoomOffset: highResData.zoomOffset,
minZoom: highResData.minZoom,
maxZoom: highResData.maxZoom
}).addTo(MapEditor.map);
MapEditor.map.fitBounds(L.latLngBounds({ lat: mapBounds.south, lng: mapBounds.west }, { lat: mapBounds.north, lng: mapBounds.east })); var highResData = Util.getHighResData();
MapEditor.markers = L.markerClusterGroup({ L.tileLayer(tileUrl, {
maxClusterRadius: 50 attribution: tileAttribution,
}); subdomains: '1234',
ppi: highResData.ppi,
tileSize: highResData.tileSize,
zoomOffset: highResData.zoomOffset,
minZoom: highResData.minZoom,
maxZoom: highResData.maxZoom
}).addTo(LMapWrapper.map);
for (var placeId in places) { if (mapId) {
if (!places.hasOwnProperty(placeId)) { LMapWrapper.map.fitBounds(L.latLngBounds({ lat: mapBounds.south, lng: mapBounds.west }, { lat: mapBounds.north, lng: mapBounds.east }));
continue; }
} }
var place = places[placeId]; LMapWrapper.loadMarkers(places);
var marker = L.marker({ lat: place.lat, lng: place.lng }, { document.getElementById('streetViewCoverSelector').disabled = true;
icon: place.noPano ? IconCollection.iconRed : IconCollection.iconGreen, },
zIndexOffset: 1000
}) hide: function () {
.addTo(MapEditor.markers) document.getElementById(LMapWrapper.divId).style.display = 'none';
.on('click', function () { },
loadMarkers: function (places) {
if (!LMapWrapper.markers) {
LMapWrapper.markers = L.markerClusterGroup({
maxClusterRadius: 50
});
} else {
LMapWrapper.markers.clearLayers();
}
for (var placeId in places) {
if (!places.hasOwnProperty(placeId)) {
continue;
}
var place = places[placeId];
var marker = L.marker({ lat: place.lat, lng: place.lng }, {
icon: place.noPano ? LMapWrapper.iconCollection.iconRed : LMapWrapper.iconCollection.iconGreen,
zIndexOffset: 1000
})
.addTo(LMapWrapper.markers)
.on('click', function () {
MapEditor.select(this);
});
marker.placeId = placeId;
}
LMapWrapper.map.addLayer(LMapWrapper.markers);
},
// TODO: check whether marker is already existing on the map for the coordinates
// or alternatively block saving for matching coordinates
placeMarker: function (latLng) {
var marker = L.marker(latLng, {
icon: LMapWrapper.iconCollection.iconBlue,
zIndexOffset: 2000
})
.addTo(LMapWrapper.markers)
.on('click', function () {
MapEditor.select(this);
});
MapEditor.select(marker);
},
panTo: function (latLng) {
LMapWrapper.map.panTo(latLng);
},
resize: function () {
LMapWrapper.map.invalidateSize(true);
},
changeMarkerIcon: function (marker, icon) {
marker.setIcon(icon);
marker.setZIndexOffset(2000);
},
removeMarker: function (marker) {
LMapWrapper.markers.removeLayer(marker);
},
toggleStreetViewCover: function () { }
};
var GMapWrapper = {
map: null,
markers: null,
divId: null,
streetViewCover: null,
streetViewCoverOn: false,
iconCollection: {
iconGreen: {
url: STATIC_ROOT + '/img/markers/marker-green.svg?rev' + REVISION,
scaledSize: new google.maps.Size(24, 32), // scaled size
origin: new google.maps.Point(0, 0), // origin
anchor: new google.maps.Point(12, 32) // anchor
},
iconRed: {
url: STATIC_ROOT + '/img/markers/marker-red.svg?rev' + REVISION,
scaledSize: new google.maps.Size(24, 32), // scaled size
origin: new google.maps.Point(0, 0), // origin
anchor: new google.maps.Point(12, 32) // anchor
},
iconBlue: {
url: STATIC_ROOT + '/img/markers/marker-blue.svg?rev' + REVISION,
scaledSize: new google.maps.Size(24, 32), // scaled size
origin: new google.maps.Point(0, 0), // origin
anchor: new google.maps.Point(12, 32) // anchor
}
},
init: function (divId, places) {
document.getElementById(divId).style.display = "block";
if (!GMapWrapper.map) {
bence marked this conversation as resolved Outdated
Outdated
Review

I would remove this and add a permanent street view cover layer to the map so the available locations will be always shown. (This is the same how the competitor does.)

Reference: https://developers.google.com/maps/documentation/javascript/reference/street-view#StreetViewCoverageLayer

Example:

                var streetViewCover = new google.maps.StreetViewCoverageLayer();
                streetViewCover.setMap(GMapWrapper.map);

I would remove this and add a permanent street view cover layer to the map so the available locations will be always shown. (This is the same how the competitor does.) Reference: https://developers.google.com/maps/documentation/javascript/reference/street-view#StreetViewCoverageLayer Example: ```js var streetViewCover = new google.maps.StreetViewCoverageLayer(); streetViewCover.setMap(GMapWrapper.map); ``` ![](https://i.ibb.co/LPjP4rr/Bildschirmfoto-vom-2021-05-02-11-27-40.png)

I personally consider the permanent street view cover layer disturbing. Can we just add another switch to toggle it?

I personally consider the permanent street view cover layer disturbing. Can we just add another switch to toggle it?
Outdated
Review

For me it's OK, then it can be done later.

For me it's OK, then it can be done later.
GMapWrapper.divId = divId;
GMapWrapper.map = new google.maps.Map(document.getElementById(GMapWrapper.divId), {
center: { lat: 0., lng: 0. },
zoom: 2,
fullscreenControl: false,
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.LEFT_BOTTOM
},
draggableCursor: 'crosshair'
});
GMapWrapper.streetViewCover = new google.maps.StreetViewCoverageLayer();
GMapWrapper.map.addListener('click', function (mapsMouseEvent) {
GMapWrapper.placeMarker({
lat: mapsMouseEvent.latLng.lat(),
lng: mapsMouseEvent.latLng.lng()
});
});
if (mapId) {
GMapWrapper.map.fitBounds({ south: mapBounds.south, west: mapBounds.west, north: mapBounds.north, east: mapBounds.east });
}
}
GMapWrapper.loadMarkers(places);
document.getElementById('streetViewCoverSelector').disabled = false;
},
hide: function () {
document.getElementById(GMapWrapper.divId).style.display = 'none';
},
loadMarkers: function (places) {
if (!GMapWrapper.markers) {
GMapWrapper.markers = new MarkerClusterer(GMapWrapper.map, [], {
imagePath: STATIC_ROOT + '/img/markers/m',
imageExtension: 'png?rev' + REVISION
});
} else {
GMapWrapper.markers.clearMarkers();
}
for (var placeId in places) {
if (!places.hasOwnProperty(placeId)) {
continue;
}
var place = places[placeId];
var marker = new google.maps.Marker({
position: {
lat: place.lat,
lng: place.lng
},
icon: place.noPano ? GMapWrapper.iconCollection.iconRed : GMapWrapper.iconCollection.iconGreen
});
marker.getLatLng = function () { return { lat: this.getPosition().lat(), lng: this.getPosition().lng() } };
marker.setLatLng = function (coords) { this.setPosition(coords) };
marker.addListener('click', function () {
MapEditor.select(this);
});
marker.placeId = placeId;
GMapWrapper.markers.addMarker(marker);
}
},
// TODO: check whether marker is already existing on the map for the coordinates
// or alternatively block saving for matching coordinates
placeMarker: function (latLng) {
var marker = new google.maps.Marker({
map: GMapWrapper.map,
position: latLng,
icon: GMapWrapper.iconCollection.iconBlue,
});
marker.getLatLng = function () { return { lat: this.getPosition().lat(), lng: this.getPosition().lng() } };
marker.setLatLng = function (coords) { this.setPosition(coords) };
marker.addListener('click', function () {
MapEditor.select(this); MapEditor.select(this);
}); });
marker.placeId = place.id; GMapWrapper.markers.addMarker(marker);
}
MapEditor.map.addLayer(MapEditor.markers); MapEditor.select(marker);
},
panTo: function (latLng) {
GMapWrapper.map.panTo(latLng);
},
resize: function () {
google.maps.event.trigger(GMapWrapper.map, 'resize');
},
changeMarkerIcon: function (marker, icon) {
marker.setIcon(icon);
},
removeMarker: function (marker) {
GMapWrapper.markers.removeMarker(marker);
},
toggleStreetViewCover: function () {
if (GMapWrapper.streetViewCoverOn) {
GMapWrapper.streetViewCover.setMap(null);
GMapWrapper.streetViewCoverOn = false;
} else {
GMapWrapper.streetViewCover.setMap(GMapWrapper.map);
GMapWrapper.streetViewCoverOn = true;
}
}
};
// initialize content of #map with google maps
MapEditor.map = GMapWrapper;
MapEditor.map.init('gmap', places);
MapEditor.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), { MapEditor.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
// switch off fullscreenControl because positioning doesn't work // switch off fullscreenControl because positioning doesn't work
@ -478,7 +680,7 @@
var coordinates = Util.extractCoordinates(coordinatesStr); var coordinates = Util.extractCoordinates(coordinatesStr);
if (coordinates.valid) { if (coordinates.valid) {
MapEditor.placeMarker(coordinates.latlng); MapEditor.map.placeMarker(coordinates.latlng);
} }
}; };
@ -491,7 +693,7 @@
jumpButton.disabled = false; jumpButton.disabled = false;
if (e.key == 'Enter') { if (e.key == 'Enter') {
MapEditor.placeMarker(coordinates.latlng); MapEditor.map.placeMarker(coordinates.latlng);
} }
} }
else { else {
@ -499,4 +701,21 @@
} }
}; };
document.getElementById('mapSelector').onclick = function () {
MapEditor.closePlace();
MapEditor.map.hide();
if (MapEditor.map === GMapWrapper) {
MapEditor.map = LMapWrapper;
MapEditor.map.init('lmap', places);
} else {
MapEditor.map = GMapWrapper;
MapEditor.map.init('gmap', places);
}
}
document.getElementById('streetViewCoverSelector').onclick = function () {
MapEditor.map.toggleStreetViewCover();
}
})(); })();

View File

@ -6,13 +6,24 @@
@js(node_modules/leaflet/dist/leaflet.js) @js(node_modules/leaflet/dist/leaflet.js)
@js(node_modules/leaflet.markercluster/dist/leaflet.markercluster.js) @js(node_modules/leaflet.markercluster/dist/leaflet.markercluster.js)
@js(https://maps.googleapis.com/maps/api/js?key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>) @js(https://maps.googleapis.com/maps/api/js?key=<?= $_ENV['GOOGLE_MAPS_JS_API_KEY'] ?>)
@js(https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js)
@js(js/map_editor.js) @js(js/map_editor.js)
@extends(templates/layout_full) @extends(templates/layout_full)
@section(subheader) @section(subheader)
<span><a href="javascript:;" id="mapName" title="Edit map data"><?= $mapName ?></a></span><!-- <span><a href="javascript:;" id="mapName" title="Edit map data"><?= $mapName ?></a></span><!--
--><span> --><span class="inline hideOnMobile" id="mapSelection">
<button id="mapSelector">
<img src="<?= $_ENV['STATIC_ROOT'] ?>/img/map.svg?rev=<?= REVISION ?>" alt="Map Selector" />
</button>
</span><!--
--><span class="inline hideOnMobile" id="mapSelection">
<button id="streetViewCoverSelector">
<img src="<?= $_ENV['STATIC_ROOT'] ?>/img/street-view-cover.svg?rev=<?= REVISION ?>" alt="Street View Conver" />
</button>
</span><!--
--><span class="inline hideOnMobile">
<input type="text" id="jumpCoordinates" placeholder="Insert coordinates here" /> <input type="text" id="jumpCoordinates" placeholder="Insert coordinates here" />
<button id="jumpButton" disabled >Jump</button> <button id="jumpButton" disabled >Jump</button>
</span><!-- </span><!--
@ -57,7 +68,10 @@
@endsection @endsection
@section(main) @section(main)
<div id="map"></div> <div id="map" class="map">
<div id="lmap" class="map"></div>
<div id="gmap" class="map"></div>
</div>
<div id="panorama"></div> <div id="panorama"></div>
<div id="noPano"> <div id="noPano">
<p class="bold">No panorama is available for this location.</p> <p class="bold">No panorama is available for this location.</p>