Spaces:
Runtime error
Runtime error
| import React, {useState, useEffect} from 'react'; | |
| import {createRoot} from 'react-dom/client'; | |
| import {Map} from 'react-map-gl'; | |
| import maplibregl from 'maplibre-gl'; | |
| import {AmbientLight, PointLight, LightingEffect} from '@deck.gl/core'; | |
| import DeckGL from '@deck.gl/react'; | |
| import {PolygonLayer} from '@deck.gl/layers'; | |
| import {TripsLayer} from '@deck.gl/geo-layers'; | |
| import { Box } from '@mui/system'; | |
| // Source data CSV, Attribution to CARTO, OpenStreetMap contributors to deck.gl trips-layer example | |
| const DATA_URL = { | |
| BUILDINGS:'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/buildings.json', // eslint-disable-line | |
| TRIPS: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/trips-v7.json' // eslint-disable-line | |
| }; | |
| const ambientLight = new AmbientLight({ | |
| color: [255, 255, 255], | |
| intensity: 1.0 | |
| }); | |
| const pointLight = new PointLight({ | |
| color: [255, 255, 255], | |
| intensity: 2.0, | |
| position: [-74.05, 40.7, 8000] | |
| }); | |
| const lightingEffect = new LightingEffect({ambientLight, pointLight}); | |
| const material = { | |
| ambient: 0.1, | |
| diffuse: 0.6, | |
| shininess: 32, | |
| specularColor: [60, 64, 70] | |
| }; | |
| const DEFAULT_THEME = { | |
| buildingColor: [74, 80, 87], | |
| trailColor0: [253, 128, 93], | |
| trailColor1: [23, 184, 190], | |
| material, | |
| effects: [lightingEffect] | |
| }; | |
| const INITIAL_VIEW_STATE = { | |
| longitude: -6.2760296, | |
| latitude: 53.362321, | |
| zoom: 13, | |
| pitch: 45, | |
| bearing: 0 | |
| }; | |
| const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json'; | |
| const landCover = [ | |
| [ | |
| [-74.0, 40.7], | |
| [-74.02, 40.7], | |
| [-74.02, 40.72], | |
| [-74.0, 40.72] | |
| ] | |
| ]; | |
| export default function Map3D({ | |
| buildings = DATA_URL.BUILDINGS, | |
| trips = DATA_URL.TRIPS, | |
| trailLength = 180, | |
| initialViewState = INITIAL_VIEW_STATE, | |
| mapStyle = MAP_STYLE, | |
| theme = DEFAULT_THEME, | |
| loopLength = 1800, | |
| animationSpeed = 1 | |
| }) { | |
| const [time, setTime] = useState(0); | |
| const [animation] = useState({}); | |
| const animate = () => { | |
| setTime(t => (t + animationSpeed) % loopLength); | |
| animation.id = window.requestAnimationFrame(animate); | |
| }; | |
| useEffect(() => { | |
| animation.id = window.requestAnimationFrame(animate); | |
| return () => window.cancelAnimationFrame(animation.id); | |
| }, [animation]); | |
| const layers = [ | |
| new PolygonLayer({ | |
| id: 'ground', | |
| data: landCover, | |
| getPolygon: f => f, | |
| stroked: false, | |
| getFillColor: [0, 0, 0, 0] | |
| }), | |
| new TripsLayer({ | |
| id: 'trips', | |
| data: trips, | |
| getPath: d => d.path, | |
| getTimestamps: d => d.timestamps, | |
| getColor: d => (d.vendor === 0 ? theme.trailColor0 : theme.trailColor1), | |
| opacity: 0.3, | |
| widthMinPixels: 2, | |
| rounded: true, | |
| trailLength, | |
| currentTime: time, | |
| shadowEnabled: false | |
| }), | |
| new PolygonLayer({ | |
| id: 'buildings', | |
| data: buildings, | |
| extruded: true, | |
| wireframe: false, | |
| opacity: 0.5, | |
| getPolygon: f => f.polygon, | |
| getElevation: f => f.height, | |
| getFillColor: theme.buildingColor, | |
| material: theme.material | |
| }) | |
| ]; | |
| return ( | |
| <Box sx={{ width: '100%', height: '100%', position: 'relative', borderRadius: '15px', overflow: 'hidden'}}> | |
| <DeckGL | |
| style={{ width: '100%', height: '100%', position: 'absolute'}} | |
| layers={layers} | |
| effects={theme.effects} | |
| initialViewState={initialViewState} | |
| controller={true} | |
| > | |
| <Map reuseMaps mapLib={maplibregl} mapStyle={mapStyle} preventStyleDiffing={true} attributionControl={false} /> | |
| </DeckGL> | |
| </Box> | |
| ); | |
| } | |