]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/history-changesets-layer.js
Switch to topLeft/bottomRight corners in updateChangesetShapes
[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.updateChangesetShapes(map);
89   },
90
91   updateChangesetShapes: function (map) {
92     for (const changeset of this._changesets.values()) {
93       const topLeft = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.minlon)),
94             bottomRight = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.maxlon)),
95             width = bottomRight.x - topLeft.x,
96             height = bottomRight.y - topLeft.y,
97             minSize = 20; // Min width/height of changeset in pixels
98
99       if (width < minSize) {
100         topLeft.x -= ((minSize - width) / 2);
101         bottomRight.x += ((minSize - width) / 2);
102       }
103
104       if (height < minSize) {
105         topLeft.y -= ((minSize - height) / 2);
106         bottomRight.y += ((minSize - height) / 2);
107       }
108
109       changeset.bounds = L.latLngBounds(map.unproject(topLeft),
110                                         map.unproject(bottomRight));
111     }
112
113     this.updateChangesetLocations(map);
114     this.reorderChangesets();
115   },
116
117   updateChangesetLocations: function (map) {
118     const mapCenterLng = map.getCenter().lng;
119
120     for (const changeset of this._changesets.values()) {
121       const changesetNorthWest = changeset.bounds.getNorthWest();
122       const changesetSouthEast = changeset.bounds.getSouthEast();
123       const changesetCenterLng = (changesetNorthWest.lng + changesetSouthEast.lng) / 2;
124       const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
125
126       if (shiftInWorldCircumferences) {
127         changesetNorthWest.lng -= shiftInWorldCircumferences * 360;
128         changesetSouthEast.lng -= shiftInWorldCircumferences * 360;
129         changeset.bounds = L.latLngBounds(changesetNorthWest, changesetSouthEast);
130
131         for (const layer of this._bboxLayers) {
132           layer.updateChangesetLayerBounds(changeset);
133         }
134       }
135     }
136   },
137
138   reorderChangesets: function () {
139     const changesetEntries = [...this._changesets];
140     changesetEntries.sort(([, a], [, b]) => b.bounds.getSize() - a.bounds.getSize());
141     this._changesets = new Map(changesetEntries);
142
143     for (const layer of this._bboxLayers) {
144       layer.clearLayers();
145     }
146
147     for (const changeset of this._changesets.values()) {
148       if (changeset.sidebarRelativePosition !== 0) {
149         this._areaLayer.addChangesetLayer(changeset);
150       }
151     }
152
153     for (const changeset of this._changesets.values()) {
154       if (changeset.sidebarRelativePosition === 0) {
155         this._areaLayer.addChangesetLayer(changeset);
156       }
157     }
158
159     for (const changeset of this._changesets.values()) {
160       if (changeset.sidebarRelativePosition !== 0) {
161         this._borderLayer.addChangesetLayer(changeset);
162       }
163     }
164
165     for (const changeset of this._changesets.values()) {
166       if (changeset.sidebarRelativePosition === 0) {
167         this._outlineLayer.addChangesetLayer(changeset);
168       }
169     }
170
171     for (const changeset of this._changesets.values()) {
172       if (changeset.sidebarRelativePosition === 0) {
173         this._borderLayer.addChangesetLayer(changeset);
174       }
175     }
176   },
177
178   toggleChangesetHighlight: function (id, state) {
179     const changeset = this._changesets.get(id);
180     if (!changeset) return;
181
182     if (state) {
183       this._highlightBackLayer.addChangesetLayer(changeset);
184       this._highlightBorderLayer.addChangesetLayer(changeset);
185     } else {
186       this._highlightBackLayer.removeLayer(id);
187       this._highlightBorderLayer.removeLayer(id);
188     }
189   },
190
191   setChangesetSidebarRelativePosition: function (id, state) {
192     const changeset = this._changesets.get(id);
193     if (!changeset) return;
194     changeset.sidebarRelativePosition = state;
195   }
196 });
197
198 OSM.HistoryChangesetsLayer.addInitHook(function () {
199   this._changesets = new Map;
200
201   this._bboxLayers = [
202     this._areaLayer = new OSM.HistoryChangesetBboxAreaLayer().addTo(this),
203     this._outlineLayer = new OSM.HistoryChangesetBboxOutlineLayer().addTo(this),
204     this._borderLayer = new OSM.HistoryChangesetBboxBorderLayer().addTo(this),
205     this._highlightBackLayer = new OSM.HistoryChangesetBboxHighlightBackLayer().addTo(this),
206     this._highlightBorderLayer = new OSM.HistoryChangesetBboxHighlightBorderLayer().addTo(this)
207   ];
208 });