Skip to content

Commit 3ad2dbf

Browse files
authored
Merge pull request #55 from firelab/opacity
Add opacity slider
2 parents e688736 + 8b17385 commit 3ad2dbf

3 files changed

Lines changed: 67 additions & 23 deletions

File tree

frontend/src/App.jsx

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default function App() {
2929
);
3030
const [timezone, setTimezone] = useState(dayjs.tz.guess());
3131
const [selectedDuration, setSelectedDuration] = useState("60");
32+
const [geotiffOpacity, setGeotiffOpacity] = useState("80");
3233

3334
// API State
3435
const [jobStatus, setJobStatus] = useState("NONE");
@@ -133,6 +134,7 @@ export default function App() {
133134
);
134135
const urls = await Promise.all(promises);
135136
setFrames(urls);
137+
setIsPlaying(true);
136138
console.log("Frames fetched successfully: ", urls);
137139
} catch (err) {
138140
console.error("Error fetching frames:", err);
@@ -297,7 +299,11 @@ export default function App() {
297299
className="w-full max-w-92 h-14"
298300
onClick={fetchRadarData}
299301
variant="contained"
300-
loading={jobStatus === "REQUESTED" || jobStatus === "PROCESSING" || jobStatus === "PENDING"}
302+
loading={
303+
jobStatus === "REQUESTED" ||
304+
jobStatus === "PROCESSING" ||
305+
jobStatus === "PENDING"
306+
}
301307
>
302308
Get Radar Data
303309
</Button>
@@ -318,36 +324,73 @@ export default function App() {
318324
{/* The CSS is a little cursed. */}
319325
<div className="flex h-full items-end">
320326
<div className=" flex md:min-w-[calc(100vw-1rem)] md:pl-92 z-999 w-full">
321-
{numFrames !== 0 && <div className="flex items-center w-full max-w-[1000px] bg-white p-2 rounded-full md:shadow-2xl md:mr-4 md:pr-4">
322-
<button
323-
type="button"
324-
onClick={() => setIsPlaying(!isPlaying)}
325-
className="mr-4 cursor-pointer text-white rounded-full bg-[#1976d2] hover:bg-[#1565c0] shadow hover:shadow-lg transition-all flex p-3 h-max"
326-
>
327-
{isPlaying ? <PauseIcon /> : <PlayArrowIcon />}
328-
</button>
329-
<Slider
330-
value={currentFrameIndex}
331-
min={0}
332-
max={frames.length > 0 ? frames.length - 1 : 0}
333-
step={1}
334-
onChange={handleSliderChange}
335-
valueLabelDisplay="auto"
336-
marks={frames.map((_, i) => ({ value: i }))}
337-
/>
338-
</div>}
327+
{numFrames !== 0 && (
328+
<div className="flex flex-col items-center w-full max-w-[800px] bg-white p-2 rounded-xl md:shadow-2xl md:mr-4 md:pr-4">
329+
<div className="flex w-full items-center">
330+
<button
331+
type="button"
332+
onClick={() => setIsPlaying(!isPlaying)}
333+
className="mr-6 ml-2 cursor-pointer text-white rounded-full bg-[#1976d2] hover:bg-[#1565c0] shadow hover:shadow-lg transition-all flex p-3 h-max"
334+
>
335+
{isPlaying ? <PauseIcon /> : <PlayArrowIcon />}
336+
</button>
337+
<Slider
338+
value={currentFrameIndex}
339+
min={0}
340+
max={frames.length > 0 ? frames.length - 1 : 0}
341+
step={1}
342+
onChange={handleSliderChange}
343+
valueLabelDisplay="auto"
344+
marks={frames.map((_, i) => ({ value: i }))}
345+
/>
346+
</div>
347+
<div className="flex w-full pt-4">
348+
<div className="flex items-center w-1/2">
349+
<p className="min-w-fit px-3 text-sm">Opacity</p>
350+
<Slider
351+
value={geotiffOpacity}
352+
min={0}
353+
max={100}
354+
step={1}
355+
onChange={(event, newValue) =>
356+
setGeotiffOpacity(newValue)
357+
}
358+
valueLabelDisplay="auto"
359+
/>
360+
<p className="min-w-fit px-3">{geotiffOpacity}%</p>
361+
</div>
362+
<div className="w-1/2">
363+
{/*TODO: Actual timestamp will go here: */}
364+
<p className="text-sm text-right">
365+
{selectedDateTime
366+
.tz(timezone)
367+
.format("YYYY-MM-DD HH:mm z")}
368+
</p>
369+
</div>
370+
</div>
371+
</div>
372+
)}
339373
</div>
340374
</div>
341375
</div>
342376

343377
<div className="bg-gray-50 min-h-100 w-full">
344-
<div className={jobStatus === "PROCESSING" || jobStatus === "REQUESTED" || jobStatus === "PENDING" ? "opacity-50" : ""}>
378+
<div
379+
className={
380+
jobStatus === "PROCESSING" ||
381+
jobStatus === "REQUESTED" ||
382+
jobStatus === "PENDING"
383+
? "opacity-50"
384+
: ""
385+
}
386+
>
345387
<LeafletMap
346388
stations={stations}
347389
selectedStation={selectedStation}
348390
setSelectedStation={setSelectedStation}
349391
frames={frames}
350392
currentFrameIndex={currentFrameIndex}
393+
opacity={geotiffOpacity}
351394
/>
352395
</div>
353396
</div>

frontend/src/components/GeoTiffAnimation.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import L from "leaflet";
33
import { useEffect, useState } from "react";
44
import { ImageOverlay } from "react-leaflet";
55

6-
export default function GeotiffAnimation({ frames, currentIndex }) {
6+
export default function GeotiffAnimation({ frames, currentIndex, opacity }) {
77
const [frameData, setFrameData] = useState([]);
88
const [loading, setLoading] = useState(true);
99

@@ -76,7 +76,7 @@ export default function GeotiffAnimation({ frames, currentIndex }) {
7676
url={frameData[currentIndex].url}
7777
bounds={frameData[currentIndex].bounds}
7878
zIndex={1000}
79-
opacity={0.7}
79+
opacity={opacity / 100}
8080
/>
8181
);
8282
}

frontend/src/components/LeafletMap.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default function LeafletMap({
2727
setSelectedStation,
2828
frames = [],
2929
currentFrameIndex,
30+
opacity
3031
}) {
3132
const [map, setMap] = useState(null);
3233
const [mapLatLng, setMapLatLng] = useState({ lat: 40.0, lng: -98.0 });
@@ -88,7 +89,7 @@ export default function LeafletMap({
8889
</Marker>
8990
);
9091
})}
91-
<GeoTiffAnimation frames={frames} currentIndex={currentFrameIndex} />
92+
<GeoTiffAnimation frames={frames} currentIndex={currentFrameIndex} opacity={opacity} />
9293
</MapContainer>
9394
</div>
9495
);

0 commit comments

Comments
 (0)