1 OSM.HistoryChangesetBboxLayer = L.FeatureGroup.extend({
2 getLayerId: function (layer) {
6 addChangesetLayer: function (changeset) {
7 const style = this._getChangesetStyle(changeset);
8 const rectangle = L.rectangle(changeset.bounds, style);
9 rectangle.id = changeset.id;
10 return this.addLayer(rectangle);
13 updateChangesetLayerBounds: function (changeset) {
14 this.getLayer(changeset.id)?.setBounds(changeset.bounds);
17 _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
18 if (sidebarRelativePosition > 0) {
19 return "changeset-above-sidebar-viewport";
20 } else if (sidebarRelativePosition < 0) {
21 return "changeset-below-sidebar-viewport";
23 return "changeset-in-sidebar-viewport";
28 OSM.HistoryChangesetBboxAreaLayer = OSM.HistoryChangesetBboxLayer.extend({
29 _getChangesetStyle: function (changeset) {
33 className: this._getSidebarRelativeClassName(changeset)
38 OSM.HistoryChangesetBboxOutlineLayer = OSM.HistoryChangesetBboxLayer.extend({
39 _getChangesetStyle: function (changeset) {
42 color: "var(--changeset-outline-color)",
44 className: this._getSidebarRelativeClassName(changeset)
49 OSM.HistoryChangesetBboxBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
50 _getChangesetStyle: function (changeset) {
53 color: "var(--changeset-border-color)",
55 className: this._getSidebarRelativeClassName(changeset)
60 OSM.HistoryChangesetBboxHighlightLayer = OSM.HistoryChangesetBboxLayer.extend({
61 _getChangesetStyle: function (changeset) {
65 color: "var(--changeset-border-color)",
66 fillColor: "var(--changeset-fill-color)",
68 className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
73 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
74 updateChangesets: function (map, changesets) {
75 this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
76 this.updateChangesetShapes(map);
79 updateChangesetShapes: function (map) {
80 for (const changeset of this._changesets.values()) {
81 const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
82 topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
83 width = topRight.x - bottomLeft.x,
84 height = bottomLeft.y - topRight.y,
85 minSize = 20; // Min width/height of changeset in pixels
87 if (width < minSize) {
88 bottomLeft.x -= ((minSize - width) / 2);
89 topRight.x += ((minSize - width) / 2);
92 if (height < minSize) {
93 bottomLeft.y += ((minSize - height) / 2);
94 topRight.y -= ((minSize - height) / 2);
97 changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
98 map.unproject(topRight));
101 this.updateChangesetLocations(map);
102 this.reorderChangesets();
105 updateChangesetLocations: function (map) {
106 const mapCenterLng = map.getCenter().lng;
108 for (const changeset of this._changesets.values()) {
109 const changesetSouthWest = changeset.bounds.getSouthWest();
110 const changesetNorthEast = changeset.bounds.getNorthEast();
111 const changesetCenterLng = (changesetSouthWest.lng + changesetNorthEast.lng) / 2;
112 const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
114 if (shiftInWorldCircumferences) {
115 changesetSouthWest.lng -= shiftInWorldCircumferences * 360;
116 changesetNorthEast.lng -= shiftInWorldCircumferences * 360;
118 for (const layer of this._bboxLayers) {
119 layer.updateChangesetLayerBounds(changeset);
125 reorderChangesets: function () {
126 const changesetEntries = [...this._changesets];
127 changesetEntries.sort(([, a], [, b]) => b.bounds.getSize() - a.bounds.getSize());
128 this._changesets = new Map(changesetEntries);
130 for (const layer of this._bboxLayers) {
134 for (const changeset of this._changesets.values()) {
135 if (changeset.sidebarRelativePosition !== 0) {
136 this._areaLayer.addChangesetLayer(changeset);
140 for (const changeset of this._changesets.values()) {
141 if (changeset.sidebarRelativePosition === 0) {
142 this._areaLayer.addChangesetLayer(changeset);
146 for (const changeset of this._changesets.values()) {
147 if (changeset.sidebarRelativePosition !== 0) {
148 this._borderLayer.addChangesetLayer(changeset);
152 for (const changeset of this._changesets.values()) {
153 if (changeset.sidebarRelativePosition === 0) {
154 this._outlineLayer.addChangesetLayer(changeset);
158 for (const changeset of this._changesets.values()) {
159 if (changeset.sidebarRelativePosition === 0) {
160 this._borderLayer.addChangesetLayer(changeset);
165 toggleChangesetHighlight: function (id, state) {
166 const changeset = this._changesets.get(id);
167 if (!changeset) return;
170 this._highlightLayer.addChangesetLayer(changeset);
172 this._highlightLayer.removeLayer(id);
176 setChangesetSidebarRelativePosition: function (id, state) {
177 const changeset = this._changesets.get(id);
178 if (!changeset) return;
179 changeset.sidebarRelativePosition = state;
183 OSM.HistoryChangesetsLayer.addInitHook(function () {
184 this._changesets = new Map;
187 this._areaLayer = new OSM.HistoryChangesetBboxAreaLayer().addTo(this),
188 this._outlineLayer = new OSM.HistoryChangesetBboxOutlineLayer().addTo(this),
189 this._borderLayer = new OSM.HistoryChangesetBboxBorderLayer().addTo(this),
190 this._highlightLayer = new OSM.HistoryChangesetBboxHighlightLayer().addTo(this)