]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/history-changesets-layer.js
Replace getLayer()?.setBounds() with updateChangesetLayerBounds()
[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   updateChangesetLayerBounds: function (changeset) {
7     this.getLayer(changeset.id)?.setBounds(changeset.bounds);
8   }
9 });
10
11 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
12   _getSidebarRelativeClassName: function ({ sidebarRelativePosition }) {
13     if (sidebarRelativePosition > 0) {
14       return "changeset-above-sidebar-viewport";
15     } else if (sidebarRelativePosition < 0) {
16       return "changeset-below-sidebar-viewport";
17     } else {
18       return "changeset-in-sidebar-viewport";
19     }
20   },
21
22   _getAreaStyle: function (changeset) {
23     return {
24       weight: 0,
25       fillOpacity: 0,
26       className: this._getSidebarRelativeClassName(changeset)
27     };
28   },
29
30   _getBorderStyle: function (changeset) {
31     return {
32       weight: 2,
33       color: "var(--changeset-border-color)",
34       fill: false,
35       className: this._getSidebarRelativeClassName(changeset)
36     };
37   },
38
39   _getHighlightStyle: function (changeset) {
40     return {
41       interactive: false,
42       weight: 4,
43       color: "var(--changeset-border-color)",
44       fillColor: "var(--changeset-fill-color)",
45       fillOpacity: 0.3,
46       className: this._getSidebarRelativeClassName(changeset) + " changeset-highlighted"
47     };
48   },
49
50   updateChangesets: function (map, changesets) {
51     this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
52     this.updateChangesetShapes(map);
53   },
54
55   updateChangesetShapes: function (map) {
56     for (const changeset of this._changesets.values()) {
57       const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
58             topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
59             width = topRight.x - bottomLeft.x,
60             height = bottomLeft.y - topRight.y,
61             minSize = 20; // Min width/height of changeset in pixels
62
63       if (width < minSize) {
64         bottomLeft.x -= ((minSize - width) / 2);
65         topRight.x += ((minSize - width) / 2);
66       }
67
68       if (height < minSize) {
69         bottomLeft.y += ((minSize - height) / 2);
70         topRight.y -= ((minSize - height) / 2);
71       }
72
73       changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
74                                         map.unproject(topRight));
75     }
76
77     this.updateChangesetLocations(map);
78     this.reorderChangesets();
79   },
80
81   updateChangesetLocations: function (map) {
82     const mapCenterLng = map.getCenter().lng;
83
84     for (const changeset of this._changesets.values()) {
85       const changesetSouthWest = changeset.bounds.getSouthWest();
86       const changesetNorthEast = changeset.bounds.getNorthEast();
87       const changesetCenterLng = (changesetSouthWest.lng + changesetNorthEast.lng) / 2;
88       const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
89
90       if (shiftInWorldCircumferences) {
91         changesetSouthWest.lng -= shiftInWorldCircumferences * 360;
92         changesetNorthEast.lng -= shiftInWorldCircumferences * 360;
93
94         for (const layer of this._bboxLayers) {
95           layer.updateChangesetLayerBounds(changeset);
96         }
97       }
98     }
99   },
100
101   reorderChangesets: function () {
102     const changesetEntries = [...this._changesets];
103     changesetEntries.sort(([, a], [, b]) => {
104       const aInViewport = !a.sidebarRelativePosition;
105       const bInViewport = !b.sidebarRelativePosition;
106       if (aInViewport !== bInViewport) return aInViewport - bInViewport;
107       return b.bounds.getSize() - a.bounds.getSize();
108     });
109     this._changesets = new Map(changesetEntries);
110
111     for (const layer of this._bboxLayers) {
112       layer.clearLayers();
113     }
114
115     for (const changeset of this._changesets.values()) {
116       const rect = L.rectangle(changeset.bounds, this._getAreaStyle(changeset));
117       rect.id = changeset.id;
118       rect.addTo(this._areaLayer);
119     }
120
121     for (const changeset of this._changesets.values()) {
122       const rect = L.rectangle(changeset.bounds, this._getBorderStyle(changeset));
123       rect.id = changeset.id;
124       rect.addTo(this._borderLayer);
125     }
126   },
127
128   toggleChangesetHighlight: function (id, state) {
129     const changeset = this._changesets.get(id);
130     if (!changeset) return;
131
132     if (state) {
133       const highlightRect = L.rectangle(changeset.bounds, this._getHighlightStyle(changeset));
134       highlightRect.id = id;
135       this._highlightLayer.addLayer(highlightRect);
136     } else {
137       this._highlightLayer.removeLayer(id);
138     }
139   },
140
141   setChangesetSidebarRelativePosition: function (id, state) {
142     const changeset = this._changesets.get(id);
143     if (!changeset) return;
144     changeset.sidebarRelativePosition = state;
145   }
146 });
147
148 OSM.HistoryChangesetsLayer.addInitHook(function () {
149   this._changesets = new Map;
150
151   this._bboxLayers = [
152     this._areaLayer = new OSM.HistoryChangesetBboxLayer().addTo(this),
153     this._borderLayer = new OSM.HistoryChangesetBboxLayer().addTo(this),
154     this._highlightLayer = new OSM.HistoryChangesetBboxLayer().addTo(this)
155   ];
156 });