@lgv/visualization-map 0.0.5 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lgv/visualization-map",
3
- "version": "0.0.5",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "description": "ES6 d3.js core visualization scaffold object and utilities for maps.",
6
6
  "main": "src/index.js",
@@ -34,6 +34,7 @@
34
34
  "browser-env": "^3.3.0",
35
35
  "c8": "^7.11.3",
36
36
  "css-loader": "^6.7.2",
37
+ "file-loader": "^6.2.0",
37
38
  "html-webpack-plugin": "^5.3.2",
38
39
  "style-loader": "^3.3.1",
39
40
  "webpack": "^5.86.0",
@@ -43,9 +44,10 @@
43
44
  "dependencies": {
44
45
  "@deck.gl/core": "^8.8.20",
45
46
  "@deck.gl/layers": "^8.8.20",
46
- "@lgv/visualization-chart": "^0.3.21",
47
+ "@lgv/visualization-chart": "^0.3.26",
47
48
  "@msrvida/vega-deck.gl": "^3.3.4",
48
49
  "leaflet": "^1.9.2",
50
+ "leaflet.markercluster": "^1.5.3",
49
51
  "vega": "^5.22.1"
50
52
  },
51
53
  "ava": {
package/src/index.js CHANGED
@@ -1,8 +1,11 @@
1
1
  import { HeatLayout } from "./layout/heat.js";
2
+ import { MapLayout } from "./layout/map.js";
2
3
 
3
4
  import { MapData } from "./structure/index.js";
4
5
 
6
+ import { Clustermap } from "./visualization/cluster.js";
5
7
  import { Heatmap } from "./visualization/heatmap.js";
8
+ import { Routemap } from "./visualization/route.js";
6
9
  import { VisualizationMap } from "./visualization/index.js";
7
10
 
8
- export { HeatLayout, Heatmap, MapData, VisualizationMap };
11
+ export { Clustermap, HeatLayout, Heatmap, MapData, MapLayout, Routemap, VisualizationMap };
@@ -1,22 +1,19 @@
1
1
  import L from "leaflet";
2
2
 
3
- import { MapData } from "../structure/index.js";
3
+ import { MapLayout } from "./map.js";
4
4
 
5
5
  /**
6
6
  * HeatLayout is a data-bound layout abstraction for a heatmap.
7
7
  * @param {array} data - geojson
8
8
  * @param {class} map - Leaflet map object
9
9
  */
10
- class HeatLayout extends MapData {
10
+ class HeatLayout extends MapLayout {
11
11
 
12
12
  constructor(data, map) {
13
13
 
14
14
  // initialize inheritance
15
15
  super(data);
16
16
 
17
- // update self
18
- this.map = map;
19
-
20
17
  }
21
18
 
22
19
  /**
@@ -0,0 +1,23 @@
1
+ import { MapData } from "../structure/index.js";
2
+
3
+ /**
4
+ * MapLayout is a data-bound layout abstraction for a leaflet map.
5
+ * @param {array} data - geojson
6
+ * @param {class} map - Leaflet map object
7
+ */
8
+ class MapLayout extends MapData {
9
+
10
+ constructor(data, map) {
11
+
12
+ // initialize inheritance
13
+ super(data);
14
+
15
+ // update self
16
+ this.map = map;
17
+
18
+ }
19
+
20
+ }
21
+
22
+ export { MapLayout };
23
+ export default MapLayout;
@@ -0,0 +1,63 @@
1
+ import L from "leaflet";
2
+ import MarkerClusterGroup from "leaflet.markercluster";
3
+ import defaultIcon from "leaflet/dist/images/marker-icon.png";
4
+
5
+ import { VisualizationMap } from "./index.js";
6
+ import { MapLayout as ML } from "../layout/map.js";
7
+
8
+ import { configuration, configurationLayout } from "../configuration.js";
9
+
10
+ /**
11
+ * Clustermap is a map abstraction for a clustered visualization.
12
+ * @param {object} data - usually array; occasionally object
13
+ * @param {string} label - identifer for chart brand
14
+ * @param {float} height - specified height of chart
15
+ * @param {object} markerIcon - Leaflet object
16
+ * @param {class} MapData - lgv data class
17
+ * @param {string} name - name of chart
18
+ * @param {float} width - specified width of chart
19
+ */
20
+ class Clustermap extends VisualizationMap {
21
+
22
+ constructor(data, width=configurationLayout.width, height=configurationLayout.height, MapLayout=null, markerIcon=L.icon({iconUrl: defaultIcon}), tileServerUrl=configurationLayout.tileserver, label=configuration.branding, name=configuration.name) {
23
+
24
+ // initialize inheritance
25
+ super(data, width, height, MapLayout ? MapLayout : new ML(data), tileServerUrl, label, name);
26
+
27
+ // set default icon
28
+ L.Marker.prototype.setIcon(markerIcon);
29
+
30
+ // initialize marker group
31
+ this.markerClusterGroup = L.markerClusterGroup();
32
+
33
+ }
34
+
35
+ /**
36
+ * Generate main visualization, i.e. everything that sits inside the map.
37
+ */
38
+ generateChart() {
39
+
40
+ // check if marker group exists
41
+ if (!this.map.hasLayer(this.markerClusterGroup)) {
42
+
43
+ // add popup info to marker
44
+ let geoJsonLayer = L.geoJson(this.data, {
45
+ onEachFeature: function (feature, layer) {
46
+ layer.bindPopup(`<div><div id="popup-poster"><div data-id="${feature.properties.id}" style="background-image: url(${feature.properties.poster})"></div></div><div><p><strong>${feature.properties.label}</strong></p><p>${feature.properties.value}</p></div>`);
47
+ }
48
+ });
49
+
50
+ // add markers to group
51
+ this.markerClusterGroup.addLayer(geoJsonLayer);
52
+
53
+ // add marker layer to map
54
+ this.map.addLayer(this.markerClusterGroup);
55
+
56
+ }
57
+
58
+ }
59
+
60
+ }
61
+
62
+ export { Clustermap };
63
+ export default Clustermap;
@@ -1,7 +1,9 @@
1
- import { degreeToRadian, LinearGrid, radianToDegree } from "@lgv/visualization-chart";
1
+ import { LinearGrid } from "@lgv/visualization-chart";
2
2
  import { mean } from "d3-array";
3
3
  import L from "leaflet";
4
4
  import "leaflet/dist/leaflet.css";
5
+ import "leaflet/dist/images/marker-shadow.png";
6
+ import "./marker-cluster.css";
5
7
 
6
8
  import { configuration, configurationLayout } from "../configuration.js";
7
9
 
@@ -25,10 +27,9 @@ class VisualizationMap extends LinearGrid {
25
27
  this.determineDataType();
26
28
 
27
29
  // determine x/y center
28
- let x = this.isFeatureCollection ? mean(this.data.features, d => d.geometry.coordinates[1]) : (this.isPoint ? this.data.coordinates[1] : (this.isXY ? mean([this.data.metadata.bounds[0][1],this.data.metadata.bounds[1][1]]) : 0));
29
-
30
- let y = this.isFeatureCollection ? mean(this.data.features, d => d.geometry.coordinates[0]) : (this.isPoint ? this.data.coordinates[0] : (this.isXY ? mean([this.data.metadata.bounds[0][0],this.data.metadata.bounds[1][0]]) : 0));
31
-
30
+ let x = this.isFeatureCollection ? mean(this.data.features, d => typeof(d.geometry.coordinates[0]) == "object" ? mean(d.geometry.coordinates.map(x => x[1]).flat()) : d.geometry.coordinates[1]) : (this.isPoint ? this.data.coordinates[1] : (this.isXY ? mean([this.data.metadata.bounds[0][1],this.data.metadata.bounds[1][1]]) : 0));
31
+ let y = this.isFeatureCollection ? mean(this.data.features, d => typeof(d.geometry.coordinates[0]) == "object" ? mean(d.geometry.coordinates.map(x => x[0]).flat()) : d.geometry.coordinates[0]) : (this.isPoint ? this.data.coordinates[0] : (this.isXY ? mean([this.data.metadata.bounds[0][0],this.data.metadata.bounds[1][0]]) : 0));
32
+
32
33
  // update self
33
34
  this.center = [x,y];
34
35
  this.map = null;
@@ -68,7 +69,7 @@ class VisualizationMap extends LinearGrid {
68
69
  * Generate main visualization, i.e. everything that sits inside the svg.
69
70
  */
70
71
  determineDataType() {
71
- this.isFeatureCollection = this.data && this.Data.source.features;
72
+ this.isFeatureCollection = this.data !== (null || undefined) && this.Data.source.features !== (null || undefined);
72
73
  this.isPoint = this.data && this.data.coordinates && this.data.type.lower() == "point";
73
74
  this.isXY = this.data && this.data.metadata && this.data.results;
74
75
  }
@@ -0,0 +1,108 @@
1
+ :root {
2
+
3
+ --marker-cluster-small: rgba(181, 226, 140, 0.6);
4
+ --marker-cluster-small-div: rgba(110, 204, 57, 0.6);
5
+ --marker-cluster-medium: rgba(241, 211, 87, 0.6);
6
+ --marker-cluster-medium-div: rgba(240, 194, 12, 0.6);
7
+ --marker-cluster-large: rgba(253, 156, 115, 0.6);
8
+ --marker-cluster-large-div: rgba(241, 128, 23, 0.6);
9
+
10
+ }
11
+
12
+ .marker-cluster-small {
13
+ background-color: var(--marker-cluster-small);
14
+ }
15
+ .marker-cluster-small div {
16
+ background-color: var(--marker-cluster-small-div);
17
+ }
18
+
19
+ .marker-cluster-medium {
20
+ background-color: var(--marker-cluster-medium);
21
+ }
22
+ .marker-cluster-medium div {
23
+ background-color: var(--marker-cluster-medium-div);
24
+ }
25
+
26
+ .marker-cluster-large {
27
+ background-color: var(--marker-cluster-large);
28
+ }
29
+ .marker-cluster-large div {
30
+ background-color: var(--marker-cluster-large-div);
31
+ }
32
+
33
+ .marker-cluster {
34
+ background-clip: padding-box;
35
+ border-radius: 2.5em;
36
+ }
37
+ .marker-cluster div {
38
+ width: 2.5em;
39
+ height: 2.5em;
40
+ text-align: center;
41
+ border-radius: 2.5em;
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content:center;
45
+ margin-left: 0.45em;
46
+ margin-top: 0.45em;
47
+ }
48
+
49
+ /***************** POP UP *****************/
50
+
51
+ .cluster-map .leaflet-popup-content {
52
+
53
+ margin-bottom: 0;
54
+ margin-left: 0;
55
+ margin-top: 0;
56
+
57
+ }
58
+
59
+ /* wrap */
60
+ .cluster-map .leaflet-popup-content > div {
61
+
62
+ display: flex;
63
+
64
+ }
65
+
66
+ /* poster parent */
67
+ .cluster-map .leaflet-popup-content > div > div:first-of-type {
68
+
69
+ height: 100%;
70
+ overflow: hidden;
71
+
72
+ }
73
+
74
+ /* poster */
75
+ .cluster-map .leaflet-popup-content > div > div:first-of-type > div {
76
+
77
+ background-position: center;
78
+ background-repeat: no-repeat;
79
+ background-size: cover;
80
+ cursor: pointer;
81
+ height: 5em;
82
+ margin-right: 1em;
83
+ transition: .3s cubic-bezier(.25,.8,.25,1);
84
+ transition-property: transform;
85
+ width: 5em;
86
+
87
+ }
88
+
89
+ .cluster-map .leaflet-popup-content > div > div:first-of-type:hover > div,
90
+ .cluster-map .leaflet-popup-content > div > div:first-of-type:focus > div {
91
+
92
+ transform: scale(1.1);
93
+
94
+ }
95
+
96
+ /* text wrap */
97
+ .cluster-map .leaflet-popup-content > div > div:last-of-type {
98
+
99
+ margin-top: 1em;
100
+
101
+ }
102
+
103
+ /* text */
104
+ .cluster-map .leaflet-popup-content p {
105
+
106
+ margin: 0;
107
+
108
+ }
@@ -0,0 +1,52 @@
1
+ import { select, Selection } from "d3-selection";
2
+ //import { transition, Transition } from "d3-transition";
3
+ import transition from "d3-transition";
4
+ import "d3-transition";
5
+ import L from "leaflet";
6
+
7
+ import { VisualizationMap } from "./index.js";
8
+ import { MapLayout as ML } from "../layout/map.js";
9
+
10
+ import { configuration, configurationLayout } from "../configuration.js";
11
+
12
+ /**
13
+ * Routemap is a map abstraction for a routing visualization.
14
+ * @param {object} data - usually array; occasionally object
15
+ * @param {string} label - identifer for chart brand
16
+ * @param {float} height - specified height of chart
17
+ * @param {class} MapData - lgv data class
18
+ * @param {string} name - name of chart
19
+ * @param {float} width - specified width of chart
20
+ */
21
+ class Routemap extends VisualizationMap {
22
+
23
+ constructor(data, width=configurationLayout.width, height=configurationLayout.height, MapLayout=null, tileServerUrl=configurationLayout.tileserver, label=configuration.branding, name=configuration.name) {
24
+
25
+ // initialize inheritance
26
+ super(data, width, height, MapLayout ? MapLayout : new ML(data), tileServerUrl, label, name);
27
+
28
+ // initialize feature group
29
+ this.geoJsonLayer = null;
30
+
31
+ }
32
+
33
+ /**
34
+ * Generate main visualization, i.e. everything that sits inside the map.
35
+ */
36
+ generateChart() {
37
+
38
+ // clear if exists
39
+ if (this.geoJsonLayer) this.geoJsonLayer.clearLayers();
40
+
41
+ // initialize feature group
42
+ this.geoJsonLayer = L.geoJSON(this.data);
43
+
44
+ // add lines
45
+ this.geoJsonLayer.addTo(this.map);
46
+
47
+ }
48
+
49
+ }
50
+
51
+ export { Routemap };
52
+ export default Routemap;
package/webpack.common.js CHANGED
@@ -33,6 +33,14 @@ const commonConfig = {
33
33
  {
34
34
  test: /\.css$/i,
35
35
  use: ["style-loader", "css-loader"]
36
+ },
37
+ {
38
+ test: /\.(png|jpe?g|gif)$/i,
39
+ use: [
40
+ {
41
+ loader: 'file-loader',
42
+ }
43
+ ]
36
44
  }
37
45
  ]
38
46
  }