Basic slideshow functionality
This commit is contained in:
@@ -4,23 +4,23 @@ import { LoadingSpinner } from '../components/LoadingSpinner'
|
|||||||
import { DrawOptions, GribMessage } from './interfaces'
|
import { DrawOptions, GribMessage } from './interfaces'
|
||||||
import { drawGrib } from './draw/drawGrib'
|
import { drawGrib } from './draw/drawGrib'
|
||||||
|
|
||||||
const CROP_BOUNDS = { x: 1906-1-440, y: 895, width: 440, height: 380 }
|
export const CROP_BOUNDS = { x: 1906-1-440, y: 895, width: 440, height: 380 }
|
||||||
|
|
||||||
export const DrawView: Component<{
|
export const DrawView: Component<{
|
||||||
isLoadingSignal: Signal<boolean>,
|
isLoadingSignal: Signal<boolean>,
|
||||||
options: DrawOptions;
|
options: DrawOptions;
|
||||||
|
canvasSignal: Signal<HTMLCanvasElement | undefined>,
|
||||||
cachedMessagesSignal: Signal<GribMessage[]>,
|
cachedMessagesSignal: Signal<GribMessage[]>,
|
||||||
cachedBuffersSignal: Signal<Uint8Array[]>,
|
cachedBuffersSignal: Signal<Uint8Array[]>,
|
||||||
cachedBitmasksSignal: Signal<Uint8Array[]>,
|
cachedBitmasksSignal: Signal<Uint8Array[]>,
|
||||||
}> = ({
|
}> = ({
|
||||||
isLoadingSignal: [getIsLoading, setIsLoading],
|
isLoadingSignal: [getIsLoading, setIsLoading],
|
||||||
options,
|
options,
|
||||||
|
canvasSignal: [getCanvas, setCanvas],
|
||||||
cachedMessagesSignal: [getCachedMessages],
|
cachedMessagesSignal: [getCachedMessages],
|
||||||
cachedBuffersSignal: [getCachedBuffers],
|
cachedBuffersSignal: [getCachedBuffers],
|
||||||
cachedBitmasksSignal: [getCachedBitmasks],
|
cachedBitmasksSignal: [getCachedBitmasks],
|
||||||
}) => {
|
}) => {
|
||||||
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>()
|
|
||||||
|
|
||||||
createEffect(async () => {
|
createEffect(async () => {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
const canvas = getCanvas()!
|
const canvas = getCanvas()!
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ export const GribFile: Component<{
|
|||||||
fetchGribBinaries(grib, getAllGribLists()).then(([messages, binaryBuffers, bitmasks]) => {
|
fetchGribBinaries(grib, getAllGribLists()).then(([messages, binaryBuffers, bitmasks]) => {
|
||||||
batch(() => {
|
batch(() => {
|
||||||
setCachedMessages(messages)
|
setCachedMessages(messages)
|
||||||
setCachedBuffers(binaryBuffers.map(b => new Uint8Array(b)))
|
setCachedBuffers(binaryBuffers)
|
||||||
setCachedBitmasks(bitmasks.map(b => new Uint8Array(b)))
|
setCachedBitmasks(bitmasks)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(err => console.warn(err.message))
|
.catch(err => console.warn(err.message))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { ReferenceTimes } from './ReferenceTimes'
|
|||||||
import { fetchGribList, fetchGribListStructure } from './fetchGrib'
|
import { fetchGribList, fetchGribListStructure } from './fetchGrib'
|
||||||
|
|
||||||
import styles from './harmonie.module.css'
|
import styles from './harmonie.module.css'
|
||||||
|
import { SlideShow } from './SlideShow'
|
||||||
|
|
||||||
export const Harmonie: Component<{}> = () => {
|
export const Harmonie: Component<{}> = () => {
|
||||||
const [getFileList, setFileList] = createSignal<string[]>([])
|
const [getFileList, setFileList] = createSignal<string[]>([])
|
||||||
@@ -15,6 +16,8 @@ export const Harmonie: Component<{}> = () => {
|
|||||||
const [getIsContour, setIsContour] = createSignal(true)
|
const [getIsContour, setIsContour] = createSignal(true)
|
||||||
const [getIsInterpolated, setIsInterpolated] = createSignal(true)
|
const [getIsInterpolated, setIsInterpolated] = createSignal(true)
|
||||||
const [getGribList, setGribList] = createSignal<GribMessage[]>([])
|
const [getGribList, setGribList] = createSignal<GribMessage[]>([])
|
||||||
|
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>()
|
||||||
|
const [getImgList, setImgList] = createSignal<[string, ImageBitmap][]>([])
|
||||||
|
|
||||||
const cachedMessagesSignal = createSignal<GribMessage[]>([])
|
const cachedMessagesSignal = createSignal<GribMessage[]>([])
|
||||||
const cachedBuffersSignal = createSignal<Uint8Array[]>([])
|
const cachedBuffersSignal = createSignal<Uint8Array[]>([])
|
||||||
@@ -62,8 +65,12 @@ export const Harmonie: Component<{}> = () => {
|
|||||||
<input type='checkbox' checked={getIsInterpolated()} onChange={()=>setIsInterpolated(!getIsInterpolated())} />
|
<input type='checkbox' checked={getIsInterpolated()} onChange={()=>setIsInterpolated(!getIsInterpolated())} />
|
||||||
</label>
|
</label>
|
||||||
<ReferenceTimes
|
<ReferenceTimes
|
||||||
|
setIsLoading={setIsLoading}
|
||||||
getFileList={getFileList}
|
getFileList={getFileList}
|
||||||
getGribList={getGribList}
|
getGribList={getGribList}
|
||||||
|
getCanvas={getCanvas}
|
||||||
|
options={{ getIsCrop: getIsCrop, getIsContour: getIsContour, getIsInterpolated: getIsInterpolated }}
|
||||||
|
setImgList={setImgList}
|
||||||
onClick={getAllGribStructure}
|
onClick={getAllGribStructure}
|
||||||
/>
|
/>
|
||||||
<ul class={styles.fileList}>
|
<ul class={styles.fileList}>
|
||||||
@@ -82,9 +89,14 @@ export const Harmonie: Component<{}> = () => {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.column}>
|
<div class={styles.column}>
|
||||||
|
<SlideShow
|
||||||
|
getCanvas={getCanvas}
|
||||||
|
getImgList={getImgList}
|
||||||
|
/>
|
||||||
<DrawView
|
<DrawView
|
||||||
isLoadingSignal={[getIsLoading, setIsLoading]}
|
isLoadingSignal={[getIsLoading, setIsLoading]}
|
||||||
options={{ getIsCrop: getIsCrop, getIsContour: getIsContour, getIsInterpolated: getIsInterpolated }}
|
options={{ getIsCrop: getIsCrop, getIsContour: getIsContour, getIsInterpolated: getIsInterpolated }}
|
||||||
|
canvasSignal={[getCanvas, setCanvas]}
|
||||||
cachedMessagesSignal={cachedMessagesSignal}
|
cachedMessagesSignal={cachedMessagesSignal}
|
||||||
cachedBuffersSignal={cachedBuffersSignal}
|
cachedBuffersSignal={cachedBuffersSignal}
|
||||||
cachedBitmasksSignal={cachedBitmasksSignal}
|
cachedBitmasksSignal={cachedBitmasksSignal}
|
||||||
|
|||||||
@@ -1,15 +1,27 @@
|
|||||||
import { Accessor, Component, createSignal } from 'solid-js'
|
import { Accessor, Component, createSignal, resetErrorBoundaries, Setter } from 'solid-js'
|
||||||
|
|
||||||
|
import { DrawOptions, GribMessage } from './interfaces'
|
||||||
|
import { fetchGribBinaries } from './fetchGrib'
|
||||||
|
import { drawGrib } from './draw/drawGrib'
|
||||||
|
import { CROP_BOUNDS } from './DrawView'
|
||||||
|
|
||||||
import styles from './harmonie.module.css'
|
import styles from './harmonie.module.css'
|
||||||
import { GribMessage } from './interfaces'
|
|
||||||
|
|
||||||
export const ReferenceTimes: Component<{
|
export const ReferenceTimes: Component<{
|
||||||
|
setIsLoading: Setter<boolean>,
|
||||||
getFileList: Accessor<string[]>,
|
getFileList: Accessor<string[]>,
|
||||||
getGribList: Accessor<GribMessage[]>,
|
getGribList: Accessor<GribMessage[]>,
|
||||||
|
getCanvas: Accessor<HTMLCanvasElement | undefined>,
|
||||||
|
options: DrawOptions,
|
||||||
|
setImgList: Setter<[string, ImageBitmap][]>,
|
||||||
onClick: () => void,
|
onClick: () => void,
|
||||||
}> = ({
|
}> = ({
|
||||||
|
setIsLoading,
|
||||||
getFileList,
|
getFileList,
|
||||||
getGribList,
|
getGribList,
|
||||||
|
getCanvas,
|
||||||
|
options,
|
||||||
|
setImgList,
|
||||||
onClick,
|
onClick,
|
||||||
}) => {
|
}) => {
|
||||||
const [getActiveDate, setActiveDate] = createSignal('')
|
const [getActiveDate, setActiveDate] = createSignal('')
|
||||||
@@ -24,13 +36,50 @@ export const ReferenceTimes: Component<{
|
|||||||
setActiveDate(newValue)
|
setActiveDate(newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getImgList(dateStr: string) {
|
||||||
|
setIsLoading(true)
|
||||||
|
const canvas = getCanvas()!
|
||||||
|
const cropBounds = options.getIsCrop() ? CROP_BOUNDS : undefined
|
||||||
|
const contour = options.getIsContour()
|
||||||
|
const isInterpolated = options.getIsInterpolated()
|
||||||
|
const forecastList = getGribList()
|
||||||
|
.filter(g => g.time.referenceTime === dateStr)
|
||||||
|
.filter(g => g.meteo.discipline === 0 && g.meteo.category === 1 && g.meteo.product === 192)
|
||||||
|
// .slice(0, 5) // TODO remove this
|
||||||
|
const promiseList = forecastList.map(async (grib): Promise<[string, ImageBitmap]> => {
|
||||||
|
const [messages, buffers, bitmasks] = await fetchGribBinaries(grib, getGribList())
|
||||||
|
drawGrib(canvas, messages, buffers, bitmasks, cropBounds, contour, isInterpolated)
|
||||||
|
// just to be sure that draws
|
||||||
|
await new Promise(resolve => setTimeout(resolve))
|
||||||
|
const img = await createImageBitmap(canvas)
|
||||||
|
return [grib.time.forecastTime, img]
|
||||||
|
})
|
||||||
|
|
||||||
|
Promise.all(promiseList)
|
||||||
|
.then(imgList => {
|
||||||
|
imgList.sort((a, b) => a[0] > b[0] ? 1 : -1)
|
||||||
|
console.log(imgList)
|
||||||
|
setImgList(imgList)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
const ctx = canvas.getContext('2d')!
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||||
|
setIsLoading(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return <ul class={styles.dateList}>
|
return <ul class={styles.dateList}>
|
||||||
{ dateList().map(dateStr =>
|
{ dateList().map(dateStr =>
|
||||||
<li>
|
<li>
|
||||||
<div onClick={() => onActiveDate(dateStr)}>
|
<div onClick={() => onActiveDate(dateStr)}>
|
||||||
{ dateStr }
|
{ dateStr }
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.controls} style={{ display: getActiveDate() === dateStr ? 'block' : 'none'}}>
|
<div
|
||||||
|
class={styles.controls}
|
||||||
|
style={{ display: getActiveDate() === dateStr ? 'block' : 'none'}}
|
||||||
|
onClick={() => getImgList(dateStr)}
|
||||||
|
>
|
||||||
{
|
{
|
||||||
getGribList().some(g => g.time.referenceTime === dateStr)
|
getGribList().some(g => g.time.referenceTime === dateStr)
|
||||||
&& <>TODO: download all forecasts</>
|
&& <>TODO: download all forecasts</>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Accessor, Component } from 'solid-js'
|
||||||
|
|
||||||
|
import styles from './harmonie.module.css'
|
||||||
|
|
||||||
|
export const SlideShow: Component<{
|
||||||
|
getCanvas: Accessor<HTMLCanvasElement | undefined>,
|
||||||
|
getImgList: Accessor<[string, ImageBitmap][]>,
|
||||||
|
}> = ({
|
||||||
|
getCanvas,
|
||||||
|
getImgList
|
||||||
|
}) => {
|
||||||
|
function draw(img: ImageBitmap) {
|
||||||
|
const canvas = getCanvas()!
|
||||||
|
const ctx = canvas.getContext('2d')!
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||||
|
ctx.drawImage(img, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ul class={styles.slideShow}>
|
||||||
|
{ getImgList().map(([forecastDate, img]) =>
|
||||||
|
<li onClick={() => draw(img)}>
|
||||||
|
{ format(forecastDate) }
|
||||||
|
</li>)}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
|
||||||
|
function format(date: string) {
|
||||||
|
return date.slice(11, 13)
|
||||||
|
// return date
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ export function fetchGribListStructure(): Promise<GribMessage[]> {
|
|||||||
export function fetchGribBinaries(
|
export function fetchGribBinaries(
|
||||||
grib: GribMessage,
|
grib: GribMessage,
|
||||||
gribList: GribMessage[],
|
gribList: GribMessage[],
|
||||||
) {
|
): Promise<[GribMessage[], Uint8Array[], Uint8Array[]]> {
|
||||||
const fileName = `harmonie_${grib.time.referenceTime}_${grib.time.forecastTime}.grib`
|
const fileName = `harmonie_${grib.time.referenceTime}_${grib.time.forecastTime}.grib`
|
||||||
const bitmaskSection = grib.sections.find(section => section.id === 6)
|
const bitmaskSection = grib.sections.find(section => section.id === 6)
|
||||||
const binarySection = grib.sections.find(section => section.id === 7)
|
const binarySection = grib.sections.find(section => section.id === 7)
|
||||||
@@ -51,4 +51,9 @@ export function fetchGribBinaries(
|
|||||||
if(isCalculatedHourPrecipitation(grib)) fetchPromise = fetchHourPrecipitationData(grib, gribList)
|
if(isCalculatedHourPrecipitation(grib)) fetchPromise = fetchHourPrecipitationData(grib, gribList)
|
||||||
|
|
||||||
return fetchPromise
|
return fetchPromise
|
||||||
|
.then(([messages, buffers, bitmasks]) => [
|
||||||
|
messages,
|
||||||
|
buffers.map(b => new Uint8Array(b)),
|
||||||
|
bitmasks.map(b => new Uint8Array(b)),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,3 +69,8 @@
|
|||||||
.dateList li .controls {
|
.dateList li .controls {
|
||||||
padding: 10px 3px;
|
padding: 10px 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slideShow li {
|
||||||
|
display: inline;
|
||||||
|
padding: 3px 5px;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user