--- /dev/null
+OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
+ _changesets: [],
+
+ updateChangesets: function (map, changesets) {
+ this._changesets = changesets;
+ this.updateChangesetShapes(map);
+ },
+
+ updateChangesetShapes: function (map) {
+ this.clearLayers();
+
+ for (const changeset of this._changesets) {
+ const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
+ topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
+ width = topRight.x - bottomLeft.x,
+ height = bottomLeft.y - topRight.y,
+ minSize = 20; // Min width/height of changeset in pixels
+
+ if (width < minSize) {
+ bottomLeft.x -= ((minSize - width) / 2);
+ topRight.x += ((minSize - width) / 2);
+ }
+
+ if (height < minSize) {
+ bottomLeft.y += ((minSize - height) / 2);
+ topRight.y -= ((minSize - height) / 2);
+ }
+
+ changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
+ map.unproject(topRight));
+ }
+
+ this._changesets.sort(function (a, b) {
+ return b.bounds.getSize() - a.bounds.getSize();
+ });
+
+ this.updateChangesetLocations(map);
+
+ for (const changeset of this._changesets) {
+ const rect = L.rectangle(changeset.bounds,
+ { weight: 2, color: "#FF9500", opacity: 1, fillColor: "#FFFFAF", fillOpacity: 0 });
+ rect.id = changeset.id;
+ rect.addTo(this);
+ }
+ },
+
+ updateChangesetLocations: function (map) {
+ const mapCenterLng = map.getCenter().lng;
+
+ for (const changeset of this._changesets) {
+ const changesetSouthWest = changeset.bounds.getSouthWest();
+ const changesetNorthEast = changeset.bounds.getNorthEast();
+ const changesetCenterLng = (changesetSouthWest.lng + changesetNorthEast.lng) / 2;
+ const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
+
+ if (shiftInWorldCircumferences) {
+ changesetSouthWest.lng -= shiftInWorldCircumferences * 360;
+ changesetNorthEast.lng -= shiftInWorldCircumferences * 360;
+
+ this.getLayer(changeset.id)?.setBounds(changeset.bounds);
+ }
+ }
+ },
+
+ highlightChangeset: function (id) {
+ this.getLayer(id)?.setStyle({ fillOpacity: 0.3, color: "#FF6600", weight: 3 });
+ },
+
+ unHighlightChangeset: function (id) {
+ this.getLayer(id)?.setStyle({ fillOpacity: 0, color: "#FF9500", weight: 2 });
+ },
+
+ getLayerId: function (layer) {
+ return layer.id;
+ }
+});
//= require jquery-simulate/jquery.simulate
+//= require ./history-changesets-layer
OSM.History = function (map) {
const page = {};
unHighlightChangeset($(this).data("changeset").id);
});
- const group = L.featureGroup()
+ const changesetsLayer = new OSM.HistoryChangesetsLayer()
.on("mouseover", function (e) {
highlightChangeset(e.layer.id);
})
clickChangeset(e.layer.id, e.originalEvent);
});
- group.getLayerId = function (layer) {
- return layer.id;
- };
-
let changesetIntersectionObserver;
function disableChangesetIntersectionObserver() {
}
function highlightChangeset(id) {
- const layer = group.getLayer(id);
- if (layer) layer.setStyle({ fillOpacity: 0.3, color: "#FF6600", weight: 3 });
+ changesetsLayer.highlightChangeset(id);
$("#changeset_" + id).addClass("selected");
}
function unHighlightChangeset(id) {
- const layer = group.getLayer(id);
- if (layer) layer.setStyle({ fillOpacity: 0, color: "#FF9500", weight: 2 });
+ changesetsLayer.unHighlightChangeset(id);
$("#changeset_" + id).removeClass("selected");
}
}
}
- function reloadChangesetsBecauseOfMapMovement() {
- OSM.router.replace("/history" + window.location.hash);
- loadFirstChangesets();
- }
-
- let changesets = [];
-
- function updateBounds() {
- group.clearLayers();
-
- for (const changeset of changesets) {
- const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
- topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
- width = topRight.x - bottomLeft.x,
- height = bottomLeft.y - topRight.y,
- minSize = 20; // Min width/height of changeset in pixels
-
- if (width < minSize) {
- bottomLeft.x -= ((minSize - width) / 2);
- topRight.x += ((minSize - width) / 2);
- }
-
- if (height < minSize) {
- bottomLeft.y += ((minSize - height) / 2);
- topRight.y -= ((minSize - height) / 2);
- }
-
- changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
- map.unproject(topRight));
+ function moveEndListener() {
+ if (location.pathname === "/history") {
+ OSM.router.replace("/history" + window.location.hash);
+ loadFirstChangesets();
+ } else {
+ changesetsLayer.updateChangesetsPositions(map);
}
+ }
- changesets.sort(function (a, b) {
- return b.bounds.getSize() - a.bounds.getSize();
- });
-
- for (const changeset of changesets) {
- const rect = L.rectangle(changeset.bounds,
- { weight: 2, color: "#FF9500", opacity: 1, fillColor: "#FFFFAF", fillOpacity: 0 });
- rect.id = changeset.id;
- rect.addTo(group);
- }
+ function zoomEndListener() {
+ changesetsLayer.updateChangesetShapes(map);
}
function updateMap() {
- changesets = $("[data-changeset]").map(function (index, element) {
+ const changesets = $("[data-changeset]").map(function (index, element) {
return $(element).data("changeset");
}).get().filter(function (changeset) {
return changeset.bbox;
});
- updateBounds();
+ changesetsLayer.updateChangesets(map, changesets);
if (location.pathname !== "/history") {
- const bounds = group.getBounds();
+ const bounds = changesetsLayer.getBounds();
if (bounds.isValid()) map.fitBounds(bounds);
}
}
};
page.load = function () {
- map.addLayer(group);
-
- if (location.pathname === "/history") {
- map.on("moveend", reloadChangesetsBecauseOfMapMovement);
- }
-
- map.on("zoomend", updateBounds);
-
+ map.addLayer(changesetsLayer);
+ map.on("moveend", moveEndListener);
+ map.on("zoomend", zoomEndListener);
loadFirstChangesets();
};
page.unload = function () {
- map.removeLayer(group);
- map.off("moveend", reloadChangesetsBecauseOfMapMovement);
- map.off("zoomend", updateBounds);
+ map.removeLayer(changesetsLayer);
+ map.off("moveend", moveEndListener);
+ map.off("zoomend", zoomEndListener);
disableChangesetIntersectionObserver();
};