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