]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/history-changesets-layer.js
Change colors of bboxes when they enter/exit the viewport
[rails.git] / app / assets / javascripts / index / history-changesets-layer.js
1 OSM.HistoryChangesetsLayer = L.FeatureGroup.extend({
2   _changesets: new Map,
3
4   _getChangesetStyle: function ({ isHighlighted, sidebarRelativePosition }) {
5     let className;
6
7     if (sidebarRelativePosition > 0) {
8       className = "changeset-above-sidebar-viewport";
9     } else if (sidebarRelativePosition < 0) {
10       className = "changeset-below-sidebar-viewport";
11     } else {
12       className = "changeset-in-sidebar-viewport";
13     }
14     if (isHighlighted) {
15       className += " changeset-highlighted";
16     }
17
18     return {
19       weight: isHighlighted ? 3 : 2,
20       color: "var(--changeset-border-color)",
21       fillColor: "var(--changeset-fill-color)",
22       fillOpacity: isHighlighted ? 0.3 : 0,
23       className
24     };
25   },
26
27   _updateChangesetStyle: function (changeset) {
28     const rect = this.getLayer(changeset.id);
29     if (!rect) return;
30
31     const style = this._getChangesetStyle(changeset);
32     rect.setStyle(style);
33     // setStyle doesn't update css classes: https://github.com/leaflet/leaflet/issues/2662
34     rect._path.classList.value = style.className;
35     rect._path.classList.add("leaflet-interactive");
36   },
37
38   updateChangesets: function (map, changesets) {
39     this._changesets = new Map(changesets.map(changeset => [changeset.id, changeset]));
40     this.updateChangesetShapes(map);
41   },
42
43   updateChangesetShapes: function (map) {
44     this.clearLayers();
45
46     for (const changeset of this._changesets.values()) {
47       const bottomLeft = map.project(L.latLng(changeset.bbox.minlat, changeset.bbox.minlon)),
48             topRight = map.project(L.latLng(changeset.bbox.maxlat, changeset.bbox.maxlon)),
49             width = topRight.x - bottomLeft.x,
50             height = bottomLeft.y - topRight.y,
51             minSize = 20; // Min width/height of changeset in pixels
52
53       if (width < minSize) {
54         bottomLeft.x -= ((minSize - width) / 2);
55         topRight.x += ((minSize - width) / 2);
56       }
57
58       if (height < minSize) {
59         bottomLeft.y += ((minSize - height) / 2);
60         topRight.y -= ((minSize - height) / 2);
61       }
62
63       changeset.bounds = L.latLngBounds(map.unproject(bottomLeft),
64                                         map.unproject(topRight));
65     }
66
67     const changesetEntries = [...this._changesets];
68     changesetEntries.sort(([, a], [, b]) => {
69       return b.bounds.getSize() - a.bounds.getSize();
70     });
71     this._changesets = new Map(changesetEntries);
72
73     this.updateChangesetLocations(map);
74
75     for (const changeset of this._changesets.values()) {
76       delete changeset.isHighlighted;
77       const rect = L.rectangle(changeset.bounds, this._getChangesetStyle(changeset));
78       rect.id = changeset.id;
79       rect.addTo(this);
80     }
81   },
82
83   updateChangesetLocations: function (map) {
84     const mapCenterLng = map.getCenter().lng;
85
86     for (const changeset of this._changesets.values()) {
87       const changesetSouthWest = changeset.bounds.getSouthWest();
88       const changesetNorthEast = changeset.bounds.getNorthEast();
89       const changesetCenterLng = (changesetSouthWest.lng + changesetNorthEast.lng) / 2;
90       const shiftInWorldCircumferences = Math.round((changesetCenterLng - mapCenterLng) / 360);
91
92       if (shiftInWorldCircumferences) {
93         changesetSouthWest.lng -= shiftInWorldCircumferences * 360;
94         changesetNorthEast.lng -= shiftInWorldCircumferences * 360;
95
96         this.getLayer(changeset.id)?.setBounds(changeset.bounds);
97       }
98     }
99   },
100
101   toggleChangesetHighlight: function (id, state) {
102     const changeset = this._changesets.get(id);
103     if (!changeset) return;
104
105     changeset.isHighlighted = state;
106     this._updateChangesetStyle(changeset);
107   },
108
109   setChangesetSidebarRelativePosition: function (id, state) {
110     const changeset = this._changesets.get(id);
111     if (!changeset) return;
112
113     changeset.sidebarRelativePosition = state;
114     this._updateChangesetStyle(changeset);
115   },
116
117   getLayerId: function (layer) {
118     return layer.id;
119   }
120 });