]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/history-changesets-layer.js
Merge updateChangesetLocations into updateChangesetsGeometry
[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
94     const mapViewCenterLng = map.getCenter().lng;
95
96     for (const changeset of this._changesets.values()) {
97       const changesetNorthWestLatLng = L.latLng(changeset.bbox.maxlat, changeset.bbox.minlon),
98             changesetSouthEastLatLng = L.latLng(changeset.bbox.minlat, changeset.bbox.maxlon),
99             changesetCenterLng = (changesetNorthWestLatLng.lng + changesetSouthEastLatLng.lng) / 2,
100             shiftInWorldCircumferences = Math.round((changesetCenterLng - mapViewCenterLng) / 360);
101
102       if (shiftInWorldCircumferences) {
103         changesetNorthWestLatLng.lng -= shiftInWorldCircumferences * 360;
104         changesetSouthEastLatLng.lng -= shiftInWorldCircumferences * 360;
105       }
106
107       const changesetMinCorner = map.project(changesetNorthWestLatLng),
108             changesetMaxCorner = map.project(changesetSouthEastLatLng),
109             changesetSizeX = changesetMaxCorner.x - changesetMinCorner.x,
110             changesetSizeY = changesetMaxCorner.y - changesetMinCorner.y;
111
112       if (changesetSizeX < changesetSizeLowerBound) {
113         changesetMinCorner.x -= (changesetSizeLowerBound - changesetSizeX) / 2;
114         changesetMaxCorner.x += (changesetSizeLowerBound - changesetSizeX) / 2;
115       }
116
117       if (changesetSizeY < changesetSizeLowerBound) {
118         changesetMinCorner.y -= (changesetSizeLowerBound - changesetSizeY) / 2;
119         changesetMaxCorner.y += (changesetSizeLowerBound - changesetSizeY) / 2;
120       }
121
122       changeset.bounds = L.latLngBounds(map.unproject(changesetMinCorner),
123                                         map.unproject(changesetMaxCorner));
124     }
125
126     this.updateChangesetsOrder();
127   },
128
129   updateChangesetsOrder: function () {
130     const changesetEntries = [...this._changesets];
131     changesetEntries.sort(([, a], [, b]) => b.bounds.getSize() - a.bounds.getSize());
132     this._changesets = new Map(changesetEntries);
133
134     for (const layer of this._bboxLayers) {
135       layer.clearLayers();
136     }
137
138     for (const changeset of this._changesets.values()) {
139       if (changeset.sidebarRelativePosition !== 0) {
140         this._areaLayer.addChangesetLayer(changeset);
141       }
142     }
143
144     for (const changeset of this._changesets.values()) {
145       if (changeset.sidebarRelativePosition === 0) {
146         this._areaLayer.addChangesetLayer(changeset);
147       }
148     }
149
150     for (const changeset of this._changesets.values()) {
151       if (changeset.sidebarRelativePosition !== 0) {
152         this._borderLayer.addChangesetLayer(changeset);
153       }
154     }
155
156     for (const changeset of this._changesets.values()) {
157       if (changeset.sidebarRelativePosition === 0) {
158         this._outlineLayer.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
169   toggleChangesetHighlight: function (id, state) {
170     const changeset = this._changesets.get(id);
171     if (!changeset) return;
172
173     if (state) {
174       this._highlightBackLayer.addChangesetLayer(changeset);
175       this._highlightBorderLayer.addChangesetLayer(changeset);
176     } else {
177       this._highlightBackLayer.removeLayer(id);
178       this._highlightBorderLayer.removeLayer(id);
179     }
180   },
181
182   setChangesetSidebarRelativePosition: function (id, state) {
183     const changeset = this._changesets.get(id);
184     if (!changeset) return;
185     changeset.sidebarRelativePosition = state;
186   }
187 });
188
189 OSM.HistoryChangesetsLayer.addInitHook(function () {
190   this._changesets = new Map;
191
192   this._bboxLayers = [
193     this._areaLayer = new OSM.HistoryChangesetBboxAreaLayer().addTo(this),
194     this._outlineLayer = new OSM.HistoryChangesetBboxOutlineLayer().addTo(this),
195     this._borderLayer = new OSM.HistoryChangesetBboxBorderLayer().addTo(this),
196     this._highlightBackLayer = new OSM.HistoryChangesetBboxHighlightBackLayer().addTo(this),
197     this._highlightBorderLayer = new OSM.HistoryChangesetBboxHighlightBorderLayer().addTo(this)
198   ];
199 });