mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-02-22 09:41:26 -08:00
removing non-openlayers code, setting map up on index page
This commit is contained in:
parent
e7d02e9b1a
commit
81e7027a4e
12 changed files with 10520 additions and 6979 deletions
|
@ -6,13 +6,7 @@ module.exports = {
|
|||
description: `Front end for Justice40 mappping tool project`,
|
||||
navigation: [
|
||||
{
|
||||
items: [{ text: 'Mapbox', link: '/mapbox' }],
|
||||
},
|
||||
{
|
||||
items: [{ text: 'Leaflet', link: '/leaflet' }],
|
||||
},
|
||||
{
|
||||
items: [{ text: 'OpenLayers', link: '/openlayers' }],
|
||||
items: [{ text: 'Map', link: '/index' }],
|
||||
},
|
||||
],
|
||||
secondaryLinks: [
|
||||
|
@ -80,7 +74,6 @@ module.exports = {
|
|||
name: `markdown-pages`,
|
||||
},
|
||||
},
|
||||
`gatsby-transformer-remark`,
|
||||
`gatsby-plugin-react-leaflet`
|
||||
`gatsby-transformer-remark`
|
||||
],
|
||||
};
|
||||
|
|
17080
justice40-frontend/package-lock.json
generated
17080
justice40-frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -15,30 +15,22 @@
|
|||
"clean": "gatsby clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdx-js/mdx": "^1.6.22",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"clipboardy": "^2.3.0",
|
||||
"colormap": "^2.3.2",
|
||||
"d3": "^6.7.0",
|
||||
"gatsby": "^3.2.1",
|
||||
"gatsby-plugin-image": "^1.3.0",
|
||||
"gatsby-plugin-manifest": "^3.3.0",
|
||||
"gatsby-plugin-mdx": "^2.3.0",
|
||||
"gatsby-plugin-react-helmet": "^4.3.0",
|
||||
"gatsby-plugin-react-leaflet": "^3.0.0",
|
||||
"gatsby-plugin-sass": "^4.3.0",
|
||||
"gatsby-plugin-sharp": "^3.3.0",
|
||||
"gatsby-plugin-sitemap": "^3.3.0",
|
||||
"gatsby-source-filesystem": "^3.3.0",
|
||||
"gatsby-transformer-remark": "^4.0.0",
|
||||
"gatsby-transformer-sharp": "^3.3.0",
|
||||
"leaflet": "^1.7.1",
|
||||
"mapbox-gl": "^2.2.0",
|
||||
"gatsby": "^3.4.1",
|
||||
"gatsby-cli": "^3.4.1",
|
||||
"gatsby-plugin-image": "^1.4.0",
|
||||
"gatsby-plugin-manifest": "^3.4.0",
|
||||
"gatsby-plugin-mdx": "^2.4.0",
|
||||
"gatsby-plugin-react-helmet": "^4.4.0",
|
||||
"gatsby-plugin-sass": "^4.4.0",
|
||||
"gatsby-plugin-sitemap": "^4.0.0",
|
||||
"gatsby-transformer-remark": "^4.1.0",
|
||||
"gatsby-transformer-sharp": "^3.4.0",
|
||||
"ol": "^6.5.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-leaflet": "^3.1.0",
|
||||
"react-map-gl": "^6.1.12",
|
||||
"sass": "^1.32.8",
|
||||
"uswds": "^2.11.1"
|
||||
}
|
||||
|
|
|
@ -2,97 +2,100 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
|
||||
// openlayers
|
||||
import Map from 'ol/Map'
|
||||
import View from 'ol/View'
|
||||
import TileLayer from 'ol/layer/Tile'
|
||||
import VectorLayer from 'ol/layer/Vector'
|
||||
import VectorSource from 'ol/source/Vector'
|
||||
import XYZ from 'ol/source/XYZ'
|
||||
import Map from 'ol/Map';
|
||||
import View from 'ol/View';
|
||||
import TileLayer from 'ol/layer/Tile';
|
||||
import XYZ from 'ol/source/XYZ';
|
||||
import MVT from 'ol/format/MVT.js';
|
||||
import VectorTileLayer from 'ol/layer/VectorTile.js';
|
||||
import VectorTileSource from 'ol/source/VectorTile.js';
|
||||
import {Fill, Style} from 'ol/style.js';
|
||||
import {fromLonLat} from 'ol/proj';
|
||||
import colormap from 'colormap';
|
||||
|
||||
function OlMapWrapper(props) {
|
||||
import * as styles from "./ol-map-wrapper.module.css";
|
||||
|
||||
const min = 0;
|
||||
const max = 1;
|
||||
const steps = 10;
|
||||
const ramp = colormap({
|
||||
colormap: 'freesurface-blue',
|
||||
nshades: steps
|
||||
});
|
||||
|
||||
function clamp(value, low, high) {
|
||||
return Math.max(low, Math.min(value, high));
|
||||
}
|
||||
|
||||
function getColor(data) {
|
||||
const f = Math.pow(clamp((data - min) / (max - min), 0, 1), 1 / 2);
|
||||
const index = Math.round(f * (steps - 1));
|
||||
return ramp[index];
|
||||
}
|
||||
|
||||
function OlMapWrapper() {
|
||||
// set intial state
|
||||
const [ map, setMap ] = useState()
|
||||
const [ featuresLayer, setFeaturesLayer ] = useState()
|
||||
|
||||
// pull refs
|
||||
const mapElement = useRef()
|
||||
|
||||
// create state ref that can be accessed in OpenLayers onclick callback function
|
||||
// https://stackoverflow.com/a/60643670
|
||||
const mapRef = useRef()
|
||||
mapRef.current = map
|
||||
|
||||
// initialize map on first render - logic formerly put into componentDidMount
|
||||
useEffect( () => {
|
||||
|
||||
// create and add vector source layer
|
||||
const initalFeaturesLayer = new VectorLayer({
|
||||
source: new VectorSource()
|
||||
})
|
||||
|
||||
// create map
|
||||
const xyzSource = new VectorTileSource({
|
||||
format: new MVT(),
|
||||
url: 'http://localhost:7800/public.maryland/{z}/{x}/{y}.mvt'
|
||||
});
|
||||
|
||||
var vtLayer = new VectorTileLayer({
|
||||
declutter: false,
|
||||
source: xyzSource,
|
||||
style: function(feature) {
|
||||
const data = feature.get('lowincpct');
|
||||
return new Style({
|
||||
fill: new Fill({
|
||||
color: getColor(data)
|
||||
}),
|
||||
});
|
||||
}
|
||||
});
|
||||
const initialMap = new Map({
|
||||
target: mapElement.current,
|
||||
layers: [
|
||||
|
||||
// USGS Topo
|
||||
new TileLayer({
|
||||
source: new XYZ({
|
||||
url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}',
|
||||
url: 'http://{a-d}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
|
||||
})
|
||||
}),
|
||||
|
||||
// Google Maps Terrain
|
||||
/* new TileLayer({
|
||||
source: new XYZ({
|
||||
url: 'http://mt0.google.com/vt/lyrs=p&hl=en&x={x}&y={y}&z={z}',
|
||||
})
|
||||
}), */
|
||||
|
||||
initalFeaturesLayer
|
||||
|
||||
vtLayer
|
||||
],
|
||||
view: new View({
|
||||
projection: 'EPSG:3857',
|
||||
center: [39.0458, -76.6413],
|
||||
zoom: 9
|
||||
center: fromLonLat([-76.6413, 39.0458]),
|
||||
zoom: 7,
|
||||
}),
|
||||
controls: []
|
||||
})
|
||||
|
||||
// save map and vector layer references to state
|
||||
setMap(initialMap)
|
||||
setFeaturesLayer(initalFeaturesLayer)
|
||||
|
||||
initialMap.once('rendercomplete', ()=>{
|
||||
performance.mark("MAP_IDLE");
|
||||
console.log("OL IS IDLE");
|
||||
});
|
||||
|
||||
vtLayer.once('tileloadend', function () {
|
||||
performance.mark("STYLE_LOADED");
|
||||
console.log("STYLE LOADED");
|
||||
});
|
||||
|
||||
},[])
|
||||
|
||||
// update map if features prop changes - logic formerly put into componentDidUpdate
|
||||
useEffect( () => {
|
||||
if (props.features.length) { // may be null on first render
|
||||
|
||||
// set features to map
|
||||
featuresLayer.setSource(
|
||||
new VectorSource({
|
||||
features: props.features // make sure features is an array
|
||||
})
|
||||
)
|
||||
|
||||
// fit map to feature extent (with 100px of padding)
|
||||
map.getView().fit(featuresLayer.getSource().getExtent(), {
|
||||
padding: [100,100,100,100]
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
},[props.features])
|
||||
|
||||
return (
|
||||
<div className="map-wrapper">
|
||||
<div ref={mapElement} id="ol-map" className="map-container"></div>
|
||||
</div>
|
||||
// render component
|
||||
return (
|
||||
<div ref={mapElement} className={styles.map}></div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default OlMapWrapper
|
|
@ -0,0 +1,3 @@
|
|||
.map {
|
||||
height: 500px;
|
||||
}
|
|
@ -1,13 +1,20 @@
|
|||
import React from 'react';
|
||||
import Layout from '../components/layout';
|
||||
import SEO from '../components/seo';
|
||||
import OlMapWrapper from '../components/ol-map-wrapper';
|
||||
import * as styles from "./index.module.css";
|
||||
|
||||
const IndexPage = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<SEO title="Justice 40 Home" />
|
||||
<div>
|
||||
Map goes here
|
||||
<div className={`grid-container .height-auto`}>
|
||||
<div className="grid-row .height-auto">
|
||||
<div className="grid-col-8">
|
||||
<OlMapWrapper />
|
||||
</div>
|
||||
<div className="grid-col-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
|
|
3
justice40-frontend/src/pages/index.module.css
Normal file
3
justice40-frontend/src/pages/index.module.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
.gridContainer {
|
||||
height: 500px;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
import * as React from "react";
|
||||
import { MapContainer, TileLayer, Marker, Popup, GeoJSON, FeatureGroup } from 'react-leaflet'
|
||||
import geojson from "../data/maryland.json";
|
||||
import Layout from '../components/layout';
|
||||
|
||||
const LeafletMap = () => {
|
||||
return (
|
||||
<MapContainer
|
||||
center={[39.0458, -76.6413]}
|
||||
zoom={8}
|
||||
style={{ height: "50vh" }}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png"
|
||||
/>
|
||||
|
||||
<FeatureGroup
|
||||
pathOptions={{ weight:0.1,
|
||||
color: 'black',
|
||||
fillColor: 'grey',
|
||||
"fill-opacity": 0.5 }}
|
||||
>
|
||||
<GeoJSON data={geojson}></GeoJSON>
|
||||
</FeatureGroup>
|
||||
|
||||
|
||||
<Marker position={[51.505, -0.09]}>
|
||||
<Popup>
|
||||
A pretty CSS3 popup. <br /> Easily customizable.
|
||||
</Popup>
|
||||
</Marker>
|
||||
</MapContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const LeafletPage = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<LeafletMap />
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default LeafletPage
|
|
@ -1,119 +0,0 @@
|
|||
import React, { useRef, useEffect, useCallback, useState } from 'react';
|
||||
import Layout from '../components/layout';
|
||||
import ReactMapGL, {Layer, Source} from 'react-map-gl';
|
||||
import * as mapboxStyles from "./mapbox.module.css";
|
||||
|
||||
|
||||
const xyzSource = {
|
||||
name: "public.maryland",
|
||||
scheme: 'xyz',
|
||||
tilejson: "2.0.0",
|
||||
minzoom: 0,
|
||||
maxzoom: 22,
|
||||
prefetchable: true,
|
||||
tiles: ["http://localhost:7800/public.maryland/{z}/{x}/{y}.mvt"],
|
||||
type: 'vector'
|
||||
};
|
||||
|
||||
const layerStyle = {
|
||||
id: 'public.maryland.MultiPolygon.fill',
|
||||
type: 'fill',
|
||||
source: "public.maryland",
|
||||
"source-layer": "public.maryland",
|
||||
paint: {
|
||||
"fill-color": [
|
||||
"interpolate",
|
||||
["linear"],
|
||||
["get", "lowincpct"],
|
||||
0,
|
||||
"white",
|
||||
1,
|
||||
"rgb(0,94,162)"
|
||||
],
|
||||
"fill-opacity": 0.5
|
||||
}
|
||||
};
|
||||
|
||||
const mapStyle = {
|
||||
'version': 8,
|
||||
'cursor': 'pointer',
|
||||
'sources': {
|
||||
'carto-light': {
|
||||
'type': 'raster',
|
||||
'tiles': [
|
||||
"https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png",
|
||||
"https://b.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png",
|
||||
"https://c.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png",
|
||||
"https://d.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png"
|
||||
]
|
||||
}
|
||||
},
|
||||
'layers': [{
|
||||
'id': 'carto-light-layer',
|
||||
'source': 'carto-light',
|
||||
'type': 'raster',
|
||||
'minzoom': 0,
|
||||
'maxzoom': 22
|
||||
}]
|
||||
};
|
||||
|
||||
const MapboxMap = () => {
|
||||
const [viewport, setViewport] = useState({
|
||||
latitude: 39.289444,
|
||||
longitude: -76.615278,
|
||||
zoom: 8
|
||||
});
|
||||
const [hoverInfo, setHoverInfo] = useState(null);
|
||||
|
||||
const onHover = useCallback(event => {
|
||||
const {
|
||||
features,
|
||||
srcEvent: {offsetX, offsetY}
|
||||
} = event;
|
||||
const hoveredFeature = features && features[0];
|
||||
|
||||
setHoverInfo(
|
||||
hoveredFeature
|
||||
? {
|
||||
feature: hoveredFeature,
|
||||
x: offsetX,
|
||||
y: offsetY
|
||||
}
|
||||
: null
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ReactMapGL
|
||||
{...viewport}
|
||||
mapboxApiAccessToken={process.env.GATSBY_MAPBOX_ACCESS_TOKEN}
|
||||
width="100%"
|
||||
height="100%"
|
||||
onViewportChange={(viewport) => setViewport(viewport)}
|
||||
mapStyle={mapStyle}
|
||||
onHover={onHover}
|
||||
>
|
||||
<Source type="vector" {...xyzSource}>
|
||||
<Layer {...layerStyle} />
|
||||
</Source>
|
||||
{hoverInfo && (
|
||||
<div className={mapboxStyles.tooltip} style={{left: hoverInfo.x, top: hoverInfo.y}}>
|
||||
<div>ID: {hoverInfo.feature.properties.id}</div>
|
||||
<div>Percent Low Income: {parseFloat(hoverInfo.feature.properties.lowincpct * 100).toFixed(2)+"%"}</div>
|
||||
</div>
|
||||
)}
|
||||
</ReactMapGL>
|
||||
);
|
||||
}
|
||||
|
||||
const MapboxPage = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<div className={mapboxStyles.mapContainer}>
|
||||
<MapboxMap />
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default MapboxPage
|
|
@ -1,19 +0,0 @@
|
|||
.mapContainer {
|
||||
height: 50vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
margin: 8px;
|
||||
padding: 4px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: #fff;
|
||||
max-width: 300px;
|
||||
font-size: 10px;
|
||||
z-index: 9;
|
||||
pointer-events: none;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import Layout from '../components/layout';
|
||||
import SEO from '../components/seo';
|
||||
import GeoJSON from 'ol/format/GeoJSON'
|
||||
import OlMapWrapper from '../components/ol-map-wrapper'
|
||||
import geojson from "../data/maryland.json";
|
||||
|
||||
const OpenLayersPage = () => {
|
||||
// set intial state
|
||||
const [ features, setFeatures ] = useState([])
|
||||
|
||||
// initialization - retrieve GeoJSON features
|
||||
useEffect( () => {
|
||||
// parse fetched geojson into OpenLayers features
|
||||
// use options to convert feature from EPSG:4326 to EPSG:3857
|
||||
const wktOptions = {
|
||||
dataProjection: 'EPSG:4326',
|
||||
featureProjection: 'EPSG:3857'
|
||||
}
|
||||
const parsedFeatures = new GeoJSON().readFeatures(geojson, wktOptions)
|
||||
setFeatures(parsedFeatures)
|
||||
},[])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Layout>
|
||||
<SEO title="OpenLayers" />
|
||||
<h1 className="margin-left-9">OpenLayers</h1>
|
||||
|
||||
<OlMapWrapper features={features} />
|
||||
|
||||
</Layout>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export default OpenLayersPage
|
||||
|
|
@ -7,15 +7,3 @@ $theme-font-path: "../../node_modules/uswds/src/fonts";
|
|||
|
||||
@import "../../node_modules/uswds/";
|
||||
@import "../../node_modules/ol/ol.css";
|
||||
@import "../../node_modules/mapbox-gl/src/css/mapbox-gl.css";
|
||||
|
||||
#map {
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
#ol-map {
|
||||
min-width: 600px;
|
||||
min-height: 50vh;
|
||||
height: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue