mapillary-js/examples/leaflet.html
2021-03-29 10:35:45 +02:00

401 lines
13 KiB
HTML

<!DOCTYPE HTML>
<html>
<head>
<title>MapillaryJS Map-Marker</title>
<link rel="icon" href="data:,">
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" href="./dist/mapillary.css" />
<link href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>
<style>
body {
margin: 0;
padding: 0;
height: 100%;
}
#mly {
position: absolute;
width: 60%;
height: 100%;
}
#map {
position: absolute;
width: 40%;
height: 100%;
right: 0;
}
</style>
</head>
<body>
<div id="mly"></div>
<div id="map"></div>
<script type="module">
import {
MarkerComponent as Marker,
Viewer,
} from './dist/mapillary.module.js';
// Setup map
const map = L.map('map').setView([56.04351888068181, 12.695600612967427], 18);
const osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
const osmAttrib = 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
const osm = new L.TileLayer(osmUrl, { maxZoom: 19, attribution: osmAttrib });
map.addLayer(osm);
map.keyboard.disable();
// Setup viewer
const mly = new Viewer({
apiClient: 'QjI1NnU0aG5FZFZISE56U3R5aWN4ZzpkYzg0NzE3MDA0YTRhZjlh',
component: {
marker: { visibleBBoxSize: 100 },
mouse: { doubleClickZoom: false },
},
container: 'mly',
});
mly.moveTo('6Zhtztzt67fWmdd4OYH44w').then(
() => { /* noop */ },
(error) => { console.error(error); });
// Show original lngLat and lngLat (if computed exist it will differ) of current
// viewer image on map. Show line linking the two points together
const mapImagePosition = {
line: L.polyline(
[[0, 0], [0, 0]],
{ color: '#0ff', weight: 1 }),
originalPos: L.circleMarker(
[0, 0],
{ radius: 7, color: '#0ff' }),
pos: L.circleMarker(
[0, 0],
{ radius: 7, color: '#00f' }),
};
mly.on('image', (viewerImageEvent) => {
const image = viewerImageEvent.image;
const mapLatLng = [
image.lngLat.lat,
image.lngLat.lng,
];
const originalMapLatLng = [
image.originalLngLat.lat,
image.originalLngLat.lng,
];
mapImagePosition.line
.setLatLngs([originalMapLatLng, mapLatLng]);
mapImagePosition.originalPos
.setLatLng(originalMapLatLng);
mapImagePosition.pos
.setLatLng(mapLatLng);
map.setView(mapLatLng);
if (!map.hasLayer(mapImagePosition.line)) {
mapImagePosition.line.addTo(map);
mapImagePosition.originalPos.addTo(map);
mapImagePosition.pos.addTo(map);
}
});
// Get marker component
const markerComponent = mly.getComponent('marker');
// Show a flat circle marker in the viewer when hovering the map
let mapHoverViewerMarker;
const removeMapHoverViewerMarker = () => {
if (!!mapHoverViewerMarker && markerComponent.has(mapHoverViewerMarker.id)) {
markerComponent.remove([mapHoverViewerMarker.id]);
mapHoverViewerMarker = null;
}
}
const onMapMouseEvent = (mapMouseEvent) => {
mapHoverViewerMarker = new Marker.CircleMarker(
'map-hover-viewer-marker-id',
{
lat: mapMouseEvent.latlng.lat,
lng: mapMouseEvent.latlng.lng,
},
{ color: '#0f0' });
markerComponent.add([mapHoverViewerMarker]);
}
map.on('mousemove', onMapMouseEvent);
map.on('mouseover', onMapMouseEvent);
map.on('mouseout', removeMapHoverViewerMarker);
// Show a flat circle marker in the viewer and a corresponding map marker when hovering the viewer
const indicator = {
id: 'indicator-id',
mapLine: L.polyline(
[[0, 0], [0, 0]],
{ color: '#0f0', weight: 1, id: 'indicator-id-line' }),
mapMarker: L.circleMarker(
[0, 0],
{ radius: 5, color: '#0f0', id: 'indicator-id-circle' }),
viewerMarker: null,
state: {
dragging: false,
lastPos: null,
moving: false,
},
};
const addMapIndicator = () => {
if (!map.hasLayer(indicator.mapLine)) {
indicator.mapLine.addTo(map);
}
if (!map.hasLayer(indicator.mapMarker)) {
indicator.mapMarker.addTo(map);
}
}
const removeMapIndicator = () => {
if (map.hasLayer(indicator.mapLine)) {
map.removeLayer(indicator.mapLine);
}
if (map.hasLayer(indicator.mapMarker)) {
map.removeLayer(indicator.mapMarker);
}
}
const removeViewerIndicator = () => {
if (!!indicator.viewerMarker &&
markerComponent.has(indicator.viewerMarker.id)) {
markerComponent.remove([indicator.viewerMarker.id]);
indicator.viewerMarker = null;
}
}
const setViewerIndicatorMarker = (viewerLngLat) => {
const viewerMarker = new Marker.CircleMarker(
indicator.id,
viewerLngLat,
{ color: '#0f0' });
markerComponent.add([viewerMarker]);
indicator.viewerMarker = viewerMarker;
}
const moveIndicatorMarker = (viewerLngLat) => {
if (indicator.state.dragging) { return; }
if (viewerLngLat == null) {
removeMapIndicator();
removeViewerIndicator();
return;
}
const mapPosLatLng = mapImagePosition.pos.getLatLng();
const mapLineString = [
[mapPosLatLng.lat, mapPosLatLng.lng],
[viewerLngLat.lat, viewerLngLat.lng],
[
mapPosLatLng.lat
+ 5 * (viewerLngLat.lat - mapPosLatLng.lat),
mapPosLatLng.lng
+ 5 * (viewerLngLat.lng - mapPosLatLng.lng),
],
];
indicator.mapLine
.setLatLngs(mapLineString);
indicator.mapMarker
.setLatLng([
viewerLngLat.lat,
viewerLngLat.lng,
]);
setViewerIndicatorMarker(viewerLngLat);
addMapIndicator();
}
const onViewerMouseEvent = (viewerMouseEvent) => {
indicator.state.lastPos = viewerMouseEvent.pixelPoint;
moveIndicatorMarker(viewerMouseEvent.lngLat);
}
mly.on('mouseup', onViewerMouseEvent);
mly.on('mouseover', onViewerMouseEvent);
mly.on('mousedown', onViewerMouseEvent);
mly.on('mousemove', (viewerMouseEvent) => {
// Store last mouse position for later unprojection
indicator.state.lastPos = viewerMouseEvent.pixelPoint;
if (indicator.state.moving ||
indicator.state.dragging) { return; }
moveIndicatorMarker(viewerMouseEvent.lngLat);
});
mly.on('mouseout', () => {
indicator.state.lastPos = null;
removeViewerIndicator();
removeMapIndicator();
});
mly.on('movestart', () => { indicator.state.moving = true; });
mly.on('moveend', () => {
indicator.state.moving = false;
if (!indicator.state.lastPos) { return; }
// Unproject the last position and move indicator marker if lngLat exist
mly
.unproject(indicator.state.lastPos)
.then(moveIndicatorMarker);
});
markerComponent.on('markerdragstart', () => {
// Remove indicators when dragging marker in the viewer
indicator.state.dragging = true;
removeViewerIndicator();
removeMapIndicator();
});
markerComponent.on('markerdragend', () => {
indicator.state.dragging = false;
if (!indicator.state.lastPos) { return; }
// Unproject the last position and move indicator marker if lngLat exist
mly
.unproject(indicator.state.lastPos)
.then(moveIndicatorMarker);
});
// Create markers on click in map or viewer
let addedMarkerId = 0;
const mapMarkers = {};
const addOrReplaceViewerMarker = (id, viewerLngLat) => {
// Create an interactive marker to be able to drag it in viewer
// and retrieve it with getMarkerIdAt method
const marker = new Marker.SimpleMarker(
id,
viewerLngLat,
{ ballColor: '#f00', color: '#f00', interactive: true });
markerComponent.add([marker]);
}
const handleMapMarkerDrag = (mapMarker) => {
// Listen to map events and act to move map and viewer markers accordingly
mapMarker.on({
mousedown: (event) => {
const onMouseMove = (e) => {
// Update both viewer marker and map marker on map marker drag
addOrReplaceViewerMarker(
mapMarker.options.id, {
lat: e.latlng.lat,
lng: e.latlng.lng,
});
mapMarker.setLatLng(e.latlng);
};
const onMouseUp = (e) => {
map.off('mousemove', onMouseMove)
map.off('mouseup', onMouseUp);
}
map.on('mousemove', onMouseMove);
map.on('mouseup', onMouseUp);
},
mouseover: (event) => {
// Remove map hover viewer marker when hovering a map marker
removeMapHoverViewerMarker();
// Disable map dragging to ensure that only map marker is dragged
map.dragging.disable();
map.off('mousemove', onMapMouseEvent);
map.off('click', mapOnClick);
},
mouseout: (event) => {
map.dragging.enable();
map.on('mousemove', onMapMouseEvent);
map.on('click', mapOnClick);
},
});
}
const createMirroredMarkers = (viewerLngLat) => {
const id = (addedMarkerId++).toString();
addOrReplaceViewerMarker(id, viewerLngLat);
const mapMarker =
L.circleMarker(
[viewerLngLat.lat, viewerLngLat.lng],
{
radius: 5,
color: '#f00',
draggable: 'true',
id: id,
})
.addTo(map);
mapMarkers[id] = mapMarker;
handleMapMarkerDrag(mapMarker);
}
mly.on('click', (viewerMouseEvent) => {
if (!viewerMouseEvent.lngLat) { return; }
markerComponent
.getMarkerIdAt(viewerMouseEvent.pixelPoint)
.then((markerId) => {
// Only create a new marker if no interactive markers are hovered
if (markerId != null) { return; }
createMirroredMarkers(viewerMouseEvent.lngLat);
});
});
const mapOnClick = (mapMouseEvent) => {
if (!mapMouseEvent.latlng) { return; }
createMirroredMarkers({
lat: mapMouseEvent.latlng.lat,
lng: mapMouseEvent.latlng.lng,
});
};
map.on('click', mapOnClick);
// Update map marker when lngLat changes for a
// marker by dragging in the viewer.
markerComponent.on("markerposition", (componentMarkerEvent) => {
const mapMarker = mapMarkers[componentMarkerEvent.marker.id];
if (!mapMarker) { return; }
mapMarker.setLatLng([
componentMarkerEvent.marker.lngLat.lat,
componentMarkerEvent.marker.lngLat.lng,
]);
});
</script>
</body>
</html>