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