]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/history-changesets-layer.js
Clean OSM.formatHash calls
[rails.git] / app / assets / javascripts / index / history-changesets-layer.js
1 OSM.HistoryChangesetBboxLayer = L.FeatureGroup.extend({
2   getLayerId: function (layer) {
3     return layer.id;
4   },
5
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);
11   },
12
13   updateChangesetLayerBounds: function (changeset) {
14     this.getLayer(changeset.id)?.setBounds(changeset.bounds);
15   },
16
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";
22     } else {
23       return "changeset-in-sidebar-viewport";
24     }
25   }
26 });
27
28 OSM.HistoryChangesetBboxAreaLayer = OSM.HistoryChangesetBboxLayer.extend({
29   _getChangesetStyle: function (changeset) {
30     return {
31       weight: 0,
32       fillOpacity: 0,
33       className: this._getSidebarRelativeClassName(changeset)
34     };
35   }
36 });
37
38 OSM.HistoryChangesetBboxOutlineLayer = OSM.HistoryChangesetBboxLayer.extend({
39   _getChangesetStyle: function (changeset) {
40     return {
41       weight: 4,
42       color: "var(--changeset-outline-color)",
43       fill: false,
44       className: this._getSidebarRelativeClassName(changeset)
45     };
46   }
47 });
48
49 OSM.HistoryChangesetBboxBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
50   _getChangesetStyle: function (changeset) {
51     return {
52       weight: 2,
53       color: "var(--changeset-border-color)",
54       fill: false,
55       className: this._getSidebarRelativeClassName(changeset)
56     };
57   }
58 });
59
60 OSM.HistoryChangesetBboxHighlightBackLayer = OSM.HistoryChangesetBboxLayer.extend({
61   _getChangesetStyle: function (changeset) {
62     return {
63       interactive: false,
64       weight: 6,
65       color: "var(--changeset-outline-color)",
66       fillColor: "var(--changeset-fill-color)",
67       fillOpacity: 0.3,
68       className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
69     };
70   }
71 });
72
73 OSM.HistoryChangesetBboxHighlightBorderLayer = OSM.HistoryChangesetBboxLayer.extend({
74   _getChangesetStyle: function (changeset) {
75     return {
76       interactive: false,
77       weight: 4,
78       color: "var(--changeset-border-color)",
79       fill: false,
80       className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
81     };
82   }
83 });
84
85 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
86   updateChangesets: function (map, changesets) {
87     this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
88     this.updateChangesetsGeometry(map);
89   },
90
91   updateChangesetsGeometry: function (map) {
92     const changesetSizeLowerBound = 20, // Min width/height of changeset in pixels
93           mapViewExpansion = 2; // Half of bbox border+outline width in pixels
94
95     const mapViewCenterLng = map.getCenter().lng,
96           mapViewPixelBounds = map.getPixelBounds();
97
98     mapViewPixelBounds.min.x -= mapViewExpansion;
99     mapViewPixelBounds.min.y -= mapViewExpansion;
100     mapViewPixelBounds.max.x += mapViewExpansion;
101     mapViewPixelBounds.max.y += mapViewExpansion;
102
103     for (const changeset of this._changesets.values()) {
104       const changesetNorthWestLatLng = L.latLng(changeset.bbox.maxlat, changeset.bbox.minlon),
105             changesetSouthEastLatLng = L.latLng(changeset.bbox.minlat, changeset.bbox.maxlon),
106             changesetCenterLng = (changesetNorthWestLatLng.lng + changesetSouthEastLatLng.lng) / 2,
107             shiftInWorldCircumferences = Math.round((changesetCenterLng - mapViewCenterLng) / 360);
108
109       if (shiftInWorldCircumferences) {
110         changesetNorthWestLatLng.lng -= shiftInWorldCircumferences * 360;
111         changesetSouthEastLatLng.lng -= shiftInWorldCircumferences * 360;
112       }
113
114       const changesetMinCorner = map.project(changesetNorthWestLatLng),
115             changesetMaxCorner = map.project(changesetSouthEastLatLng),
116             changesetSizeX = changesetMaxCorner.x - changesetMinCorner.x,
117             changesetSizeY = changesetMaxCorner.y - changesetMinCorner.y;
118
119       if (changesetSizeX < changesetSizeLowerBound) {
120         changesetMinCorner.x -= (changesetSizeLowerBound - changesetSizeX) / 2;
121         changesetMaxCorner.x += (changesetSizeLowerBound - changesetSizeX) / 2;
122       }
123
124       if (changesetSizeY < changesetSizeLowerBound) {
125         changesetMinCorner.y -= (changesetSizeLowerBound - changesetSizeY) / 2;
126         changesetMaxCorner.y += (changesetSizeLowerBound - changesetSizeY) / 2;
127       }
128
129       changeset.bounds = L.latLngBounds(map.unproject(changesetMinCorner),
130                                         map.unproject(changesetMaxCorner));
131
132       const changesetPixelBounds = L.bounds(changesetMinCorner, changesetMaxCorner);
133
134       changeset.hasEdgesInMapView = changesetPixelBounds.overlaps(mapViewPixelBounds) &&
135                                     !changesetPixelBounds.contains(mapViewPixelBounds);
136     }
137
138     this.updateChangesetsOrder();
139   },
140
141   updateChangesetsOrder: function () {
142     const changesetEntries = [...this._changesets];
143     changesetEntries.sort(([, a], [, b]) => b.bounds.getSize() - a.bounds.getSize());
144     this._changesets = new Map(changesetEntries);
145
146     for (const layer of this._bboxLayers) {
147       layer.clearLayers();
148     }
149
150     for (const changeset of this._changesets.values()) {
151       if (changeset.sidebarRelativePosition !== 0 && changeset.hasEdgesInMapView) {
152         this._areaLayer.addChangesetLayer(changeset);
153       }
154     }
155
156     for (const changeset of this._changesets.values()) {
157       if (changeset.sidebarRelativePosition === 0 && changeset.hasEdgesInMapView) {
158         this._areaLayer.addChangesetLayer(changeset);
159       }
160     }
161
162     for (const changeset of this._changesets.values()) {
163       if (changeset.sidebarRelativePosition !== 0) {
164         this._borderLayer.addChangesetLayer(changeset);
165       }
166     }
167
168     for (const changeset of this._changesets.values()) {
169       if (changeset.sidebarRelativePosition === 0) {
170         this._outlineLayer.addChangesetLayer(changeset);
171       }
172     }
173
174     for (const changeset of this._changesets.values()) {
175       if (changeset.sidebarRelativePosition === 0) {
176         this._borderLayer.addChangesetLayer(changeset);
177       }
178     }
179   },
180
181   toggleChangesetHighlight: function (id, state) {
182     const changeset = this._changesets.get(id);
183     if (!changeset) return;
184
185     if (state) {
186       this._highlightBackLayer.addChangesetLayer(changeset);
187       this._highlightBorderLayer.addChangesetLayer(changeset);
188     } else {
189       this._highlightBackLayer.removeLayer(id);
190       this._highlightBorderLayer.removeLayer(id);
191     }
192   },
193
194   setChangesetSidebarRelativePosition: function (id, state) {
195     const changeset = this._changesets.get(id);
196     if (!changeset) return;
197     changeset.sidebarRelativePosition = state;
198   }
199 });
200
201 OSM.HistoryChangesetsLayer.addInitHook(function () {
202   this._changesets = new Map;
203
204   this._bboxLayers = [
205     this._areaLayer = new OSM.HistoryChangesetBboxAreaLayer().addTo(this),
206     this._outlineLayer = new OSM.HistoryChangesetBboxOutlineLayer().addTo(this),
207     this._borderLayer = new OSM.HistoryChangesetBboxBorderLayer().addTo(this),
208     this._highlightBackLayer = new OSM.HistoryChangesetBboxHighlightBackLayer().addTo(this),
209     this._highlightBorderLayer = new OSM.HistoryChangesetBboxHighlightBorderLayer().addTo(this)
210   ];
211 });