mirror of
https://github.com/mapillary/mapillary-js.git
synced 2025-12-08 17:35:55 +00:00
440 lines
15 KiB
HTML
440 lines
15 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 {
|
|
CircleMarker,
|
|
SimpleMarker,
|
|
Viewer,
|
|
} from "/dist/mapillary.module.js";
|
|
import { accessToken } from "/doc-src/.access-token/token.js";
|
|
|
|
const imageId = "147617667372938";
|
|
|
|
// 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({
|
|
accessToken,
|
|
component: {
|
|
marker: { visibleBBoxSize: 100 },
|
|
},
|
|
container: "mly",
|
|
});
|
|
|
|
mly.moveTo(imageId).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 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 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 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>
|