Files
WeatherTool/web/src/harmonie/SlideShow.tsx
T

91 lines
2.7 KiB
TypeScript
Raw Normal View History

import { Accessor, Component, createSignal } from 'solid-js'
2025-02-21 23:07:49 +02:00
import styles from './harmonie.module.css'
import { downloadImagesAsZip } from '../helpers/download'
2025-02-21 23:07:49 +02:00
export const SlideShow: Component<{
getIsLoading: Accessor<boolean>,
2025-02-21 23:07:49 +02:00
getCanvas: Accessor<HTMLCanvasElement | undefined>,
2025-02-23 20:21:11 +02:00
getImgList: Accessor<[string, ImageBitmap | undefined][]>,
2025-02-24 18:55:39 +02:00
getRefDate: Accessor<string>,
2025-02-21 23:07:49 +02:00
}> = ({
getIsLoading,
2025-02-21 23:07:49 +02:00
getCanvas,
2025-02-24 18:55:39 +02:00
getImgList,
getRefDate,
2025-02-21 23:07:49 +02:00
}) => {
const [getActive, setActive] = createSignal(-1)
const [getIsPlaying, setIsPlaying] = createSignal(false)
function draw(i: number) {
2025-02-21 23:07:49 +02:00
const canvas = getCanvas()!
const ctx = canvas.getContext('2d')!
ctx.clearRect(0, 0, canvas.width, canvas.height)
setActive(i)
const img = getImgList()[i][1]
2025-02-23 20:21:11 +02:00
if (!img) return;
2025-02-21 23:07:49 +02:00
ctx.drawImage(img, 0, 0)
}
function next(delta = 1) {
const count = getImgList().length
if (!count) return;
const result = (getActive() + delta) % count
const nextValue = result >= 0 ? result : count - 1
setActive(nextValue)
draw(nextValue)
}
function prev() { next(-1) }
function areControlsVisible(): boolean {
return getImgList().length > 0 && !getIsLoading()
}
let playingTimeout = 0
function play() {
if (getIsPlaying()) {
clearTimeout(playingTimeout)
setIsPlaying(false)
return;
}
function loop() {
next()
playingTimeout = setTimeout(loop, 300)
}
setIsPlaying(true)
loop()
}
function download() {
const imgs = getImgList().filter(([,img]) => !!img) as [string, ImageBitmap][]
2025-02-24 18:55:39 +02:00
downloadImagesAsZip(imgs, getRefDate())
}
return <>
<div class={styles.slideShowControls} style={{visibility: areControlsVisible() ? 'visible' : 'hidden'}}>
<div class={styles.leftButtons}>
<input type='button' value='prev' onClick={prev} />
<input type='button' value={getIsPlaying()?'pause':'play'} onClick={play} />
<input type='button' value='next' onClick={() => next()} />
</div>
2025-02-24 18:55:39 +02:00
<input type='button' value='download .zip' onClick={download} />
</div>
<ul class={styles.slideShowList}>
{ getImgList().map(([forecastDate, img], i) =>
<li
class={`${img?styles.withImg:''} ${i===getActive()?styles.active:''}`}
onClick={() => draw(i)}
>
{ format(forecastDate) }
</li>)}
</ul>
</>
2025-02-21 23:07:49 +02:00
}
function format(date: string) {
return date.slice(11, 13) // 2025-02-23T1500Z -> 15
2025-02-21 23:07:49 +02:00
}