|
|
import { load } from '@loaders.gl/core';
|
|
|
import { CSVLoader } from '@loaders.gl/csv';
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
|
import { Select, Slider, Space, Spin } from 'antd';
|
|
|
import { scaleLinear } from 'd3-scale';
|
|
|
import { interpolateViridis } from 'd3-scale-chromatic';
|
|
|
import { DeckGL, GridCellLayer, ScatterplotLayer } from 'deck.gl';
|
|
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
|
import { useState } from 'react';
|
|
|
import Map from 'react-map-gl/maplibre';
|
|
|
|
|
|
const colorScale = scaleLinear<string, string>().domain([0, 10000]).range([interpolateViridis(0), interpolateViridis(1)]);
|
|
|
const radiusScale = scaleLinear().domain([0, 12000]).range([50, 250]);
|
|
|
|
|
|
function App() {
|
|
|
const [value, setValue] = useState(0);
|
|
|
const [attr, setAttr] = useState("00:00:00");
|
|
|
const [day, setDay] = useState("2023-12-01")
|
|
|
|
|
|
const { isPending, error, data } = useQuery({
|
|
|
queryKey: [day],
|
|
|
queryFn: () => load(`./${day}.csv`, CSVLoader, { csv: {} }),
|
|
|
})
|
|
|
|
|
|
if (error) {
|
|
|
console.log(error)
|
|
|
}
|
|
|
|
|
|
const layers = isPending ? [] : [
|
|
|
new GridCellLayer({
|
|
|
id: 'deckgl-grid',
|
|
|
//@ts-ignore
|
|
|
data: data.data,
|
|
|
getPosition: d => [d.x, d.y],
|
|
|
//@ts-ignore
|
|
|
getFillColor: d => colorScale(d[attr]).slice(4, -1).split(", ").map(Number),
|
|
|
cellSize: 505,
|
|
|
extruded: false,
|
|
|
updateTriggers: {
|
|
|
getFillColor: [attr],
|
|
|
}
|
|
|
}),
|
|
|
new ScatterplotLayer({
|
|
|
id: 'deckgl-circle2',
|
|
|
//@ts-ignore
|
|
|
// data: isPending ? [] : data.data,
|
|
|
getPosition: d => [d.x, d.y],
|
|
|
//@ts-ignore
|
|
|
getFillColor: d => colorScale(d[attr]).slice(4, -1).split(", ").map(Number),
|
|
|
getRadius: d => radiusScale(d[attr]),
|
|
|
updateTriggers: {
|
|
|
getFillColor: [attr],
|
|
|
getRadius: [attr]
|
|
|
}
|
|
|
}),
|
|
|
];
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
<DeckGL
|
|
|
initialViewState={{
|
|
|
longitude: 37.028,
|
|
|
latitude: 55.778,
|
|
|
zoom: 7
|
|
|
}}
|
|
|
controller
|
|
|
layers={layers}
|
|
|
>
|
|
|
<Map mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json" hash={true} />
|
|
|
</DeckGL>
|
|
|
<Space style={{ position: "absolute", zIndex: 1, justifyContent: "center", padding: 30 }} direction='vertical'>
|
|
|
<Spin spinning={isPending} />
|
|
|
<Select
|
|
|
onChange={setDay}
|
|
|
options={[{ value: "2023-12-01" }, { value: "2023-12-02" }]}
|
|
|
value={day}
|
|
|
/>
|
|
|
<Slider
|
|
|
value={value}
|
|
|
min={0}
|
|
|
max={47}
|
|
|
onChange={e => setValue(e)}
|
|
|
onChangeComplete={hour => {
|
|
|
const hours = Math.floor(hour / 2).toString().padStart(2, "0");
|
|
|
const minutes = ((hour % 2) * 30).toString().padStart(2, "0");
|
|
|
const field = hours + ":" + minutes + ":00";
|
|
|
setAttr(field);
|
|
|
}}
|
|
|
/>
|
|
|
<p id="time">{attr}</p>
|
|
|
<button onClick={() => {
|
|
|
setValue((value + 1))
|
|
|
//@ts-ignore
|
|
|
const hour = parseInt(value);
|
|
|
const hours = Math.floor(hour / 2).toString().padStart(2, "0");
|
|
|
const minutes = ((hour % 2) * 30).toString().padStart(2, "0");
|
|
|
const field = hours + ":" + minutes + ":00";
|
|
|
setAttr(field);
|
|
|
}}>Плюс</button>
|
|
|
</Space>
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
}
|
|
|
|
|
|
export default App
|