Skip to content

Commit fc63beb

Browse files
author
Vincent van der Wal
committed
style for mobile
1 parent 26f3c81 commit fc63beb

File tree

4 files changed

+167
-165
lines changed

4 files changed

+167
-165
lines changed

src/om-protocol.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ const getTile = async ({ z, x, y }: TileIndex, omUrl: string): Promise<ImageBitm
104104

105105
const worker = new TileWorker();
106106

107-
let iconList = {};
108-
if (variable.value.startsWith('wind')) {
109-
iconList = arrowPixelData;
110-
}
111-
112107
worker.postMessage({
113108
type: 'GT',
114109
x,
@@ -118,7 +113,6 @@ const getTile = async ({ z, x, y }: TileIndex, omUrl: string): Promise<ImageBitm
118113
data,
119114
domain,
120115
variable,
121-
iconPixelData: iconList,
122116
dark: dark
123117
});
124118
const tilePromise = new Promise<ImageBitmap>((resolve) => {

src/routes/+page.svelte

Lines changed: 71 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -476,95 +476,97 @@
476476
</Sheet.Root>
477477

478478
<Drawer.Root bind:open={drawerOpen}>
479-
<Drawer.Content class="flex h-1/2 items-center">
480-
<div class="absolute top-2 left-2">
481-
Domain: {domain.value} <br />
482-
Model: {modelRunSelected.getUTCFullYear()}-{pad(modelRunSelected.getUTCMonth() + 1)}-{pad(
483-
modelRunSelected.getUTCDate()
484-
)}T{pad(modelRunSelected.getUTCHours())}:00Z <br />
485-
Time: {timeSelected.getUTCFullYear()}-{pad(timeSelected.getUTCMonth() + 1)}-{pad(
486-
timeSelected.getUTCDate()
487-
)}T{pad(timeSelected.getUTCHours())}:00Z <br />
488-
Variable: {variable.value}
489-
<br />
490-
</div>
491-
<div class="flex overflow-scroll">
492-
<div class="flex w-1/3 flex-col gap-3 pr-3">
493-
<h2 class="text-lg font-bold">Domains</h2>
494-
{#each domains as d, i (i)}
495-
<Button
496-
class="cursor-pointer bg-blue-200 hover:bg-blue-600 {d.value === domain.value
497-
? 'bg-blue-400'
498-
: ''}"
499-
onclick={() => {
500-
domain = d;
501-
url.searchParams.set('domain', d.value);
502-
history.pushState({}, '', url);
503-
changeOMfileURL();
504-
}}>{d.label}</Button
505-
>
506-
{/each}
479+
<Drawer.Content class=" h-1/2 ">
480+
<div class="flex w-full flex-col items-center overflow-y-scroll">
481+
<div class="mt-3 md:absolute md:top-3 md:left-3">
482+
Domain: {domain.value} <br />
483+
Model: {modelRunSelected.getUTCFullYear()}-{pad(modelRunSelected.getUTCMonth() + 1)}-{pad(
484+
modelRunSelected.getUTCDate()
485+
)}T{pad(modelRunSelected.getUTCHours())}:00Z <br />
486+
Time: {timeSelected.getUTCFullYear()}-{pad(timeSelected.getUTCMonth() + 1)}-{pad(
487+
timeSelected.getUTCDate()
488+
)}T{pad(timeSelected.getUTCHours())}:00Z <br />
489+
Variable: {variable.value}
490+
<br />
507491
</div>
508-
509-
{#await latestRequest}
510-
<div class="flex w-1/3 flex-col gap-1 px-3">
511-
<h2 class="mb-2 text-lg font-bold">Valid times in model run</h2>
512-
Loading latest times...
513-
</div>
514-
<div class="flex w-1/3 flex-col gap-1 pl-3">
515-
<h2 class="mb-2 text-lg font-bold">Variables</h2>
516-
Loading domain variables...
517-
</div>
518-
{:then latest}
519-
<div class="flex w-1/3 flex-col gap-1 px-3">
520-
<h2 class="mb-2 text-lg font-bold">Valid times in model run</h2>
521-
{#each latest.valid_times as vt, i (i)}
522-
{@const d = new Date(vt)}
492+
<div class="mt-3 flex flex-col gap-6 md:flex-row md:gap-0">
493+
<div class="flex flex-col gap-3 md:w-1/3 md:pr-3">
494+
<h2 class="text-lg font-bold">Domains</h2>
495+
{#each domains as d, i (i)}
523496
<Button
524-
class="cursor-pointer bg-blue-200 hover:bg-blue-600 {d.getTime() ===
525-
timeSelected.getTime()
497+
class="cursor-pointer bg-blue-200 hover:bg-blue-600 {d.value === domain.value
526498
? 'bg-blue-400'
527499
: ''}"
528500
onclick={() => {
529-
timeSelected = d;
530-
url.searchParams.set('time', d.toISOString().replace(/[:Z]/g, '').slice(0, 15));
501+
domain = d;
502+
url.searchParams.set('domain', d.value);
531503
history.pushState({}, '', url);
532504
changeOMfileURL();
533-
}}
534-
>{d.getUTCFullYear() +
535-
'-' +
536-
pad(d.getUTCMonth() + 1) +
537-
'-' +
538-
d.getUTCDate() +
539-
' ' +
540-
d.getUTCHours() +
541-
':' +
542-
pad(d.getUTCMinutes())}</Button
505+
}}>{d.label}</Button
543506
>
544507
{/each}
545508
</div>
546-
{#if timeValid}
547-
<div class="flex w-1/3 flex-col gap-1 pl-3">
548-
<h2 class="mb-2 text-lg font-bold">Variables</h2>
549509

550-
{#each latest.variables as vr, i (i)}
510+
{#await latestRequest}
511+
<div class="flex flex-col gap-1 md:w-1/3 md:px-3">
512+
<h2 class="mb-2 text-lg font-bold">Valid times in model run</h2>
513+
Loading latest times...
514+
</div>
515+
<div class="flex flex-col gap-1 md:w-1/3 md:pl-3">
516+
<h2 class="mb-2 text-lg font-bold">Variables</h2>
517+
Loading domain variables...
518+
</div>
519+
{:then latest}
520+
<div class="flex flex-col gap-1 md:w-1/3 md:px-3">
521+
<h2 class="mb-2 text-lg font-bold">Valid times in model run</h2>
522+
{#each latest.valid_times as vt, i (i)}
523+
{@const d = new Date(vt)}
551524
<Button
552-
class="cursor-pointer bg-blue-200 hover:bg-blue-600 {variable.value === vr
525+
class="cursor-pointer bg-blue-200 hover:bg-blue-600 {d.getTime() ===
526+
timeSelected.getTime()
553527
? 'bg-blue-400'
554528
: ''}"
555529
onclick={() => {
556-
variable = variables.find((v) => v.value === vr) ?? variables[0];
557-
url.searchParams.set('variable', vr);
530+
timeSelected = d;
531+
url.searchParams.set('time', d.toISOString().replace(/[:Z]/g, '').slice(0, 15));
558532
history.pushState({}, '', url);
559533
changeOMfileURL();
560-
}}>{vr}</Button
534+
}}
535+
>{d.getUTCFullYear() +
536+
'-' +
537+
pad(d.getUTCMonth() + 1) +
538+
'-' +
539+
d.getUTCDate() +
540+
' ' +
541+
d.getUTCHours() +
542+
':' +
543+
pad(d.getUTCMinutes())}</Button
561544
>
562545
{/each}
563546
</div>
564-
{:else}
565-
<div class="flex min-w-1/4 flex-col gap-1">No valid time selected</div>
566-
{/if}
567-
{/await}
547+
{#if timeValid}
548+
<div class="flex flex-col gap-1 md:w-1/3 md:pl-3">
549+
<h2 class="mb-2 text-lg font-bold">Variables</h2>
550+
551+
{#each latest.variables as vr, i (i)}
552+
<Button
553+
class="cursor-pointer bg-blue-200 hover:bg-blue-600 {variable.value === vr
554+
? 'bg-blue-400'
555+
: ''}"
556+
onclick={() => {
557+
variable = variables.find((v) => v.value === vr) ?? variables[0];
558+
url.searchParams.set('variable', vr);
559+
history.pushState({}, '', url);
560+
changeOMfileURL();
561+
}}>{vr}</Button
562+
>
563+
{/each}
564+
</div>
565+
{:else}
566+
<div class="flex min-w-1/4 flex-col gap-1">No valid time selected</div>
567+
{/if}
568+
{/await}
569+
</div>
568570
</div>
569571
</Drawer.Content>
570572
</Drawer.Root>

src/worker.ts

Lines changed: 90 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -20,68 +20,68 @@ import type { Domain, IndexAndFractions } from './types';
2020
const TILE_SIZE = Number(import.meta.env.VITE_TILE_SIZE) * 2;
2121
const OPACITY = Number(import.meta.env.VITE_TILE_OPACITY);
2222

23-
const rotatePoint = (cx: number, cy: number, theta: number, x: number, y: number) => {
24-
let xt = Math.cos(theta) * (x - cx) - Math.sin(theta) * (y - cy) + cx;
25-
let yt = Math.sin(theta) * (x - cx) + Math.cos(theta) * (y - cy) + cy;
26-
27-
return [xt, yt];
28-
};
29-
30-
const drawArrow = (
31-
rgba: Uint8ClampedArray,
32-
iBase: number,
33-
jBase: number,
34-
x: number,
35-
y: number,
36-
z: number,
37-
nx: number,
38-
domain: Domain,
39-
projectionGrid: ProjectionGrid,
40-
values: TypedArray,
41-
directions: TypedArray,
42-
boxSize = TILE_SIZE / 8,
43-
iconPixelData: IconListPixels
44-
): void => {
45-
const northArrow = iconPixelData['0'];
46-
47-
let iCenter = iBase + Math.floor(boxSize / 2);
48-
let jCenter = jBase + Math.floor(boxSize / 2);
49-
50-
const lat = tile2lat(y + iCenter / TILE_SIZE, z);
51-
const lon = tile2lon(x + jCenter / TILE_SIZE, z);
52-
53-
const { index, xFraction, yFraction } = getIndexAndFractions(lat, lon, domain, projectionGrid);
54-
55-
let px = interpolateLinear(values, nx, index, xFraction, yFraction);
56-
57-
let direction = degreesToRadians(interpolateLinear(directions, nx, index, xFraction, yFraction));
58-
59-
if (direction) {
60-
for (let i = 0; i < boxSize; i++) {
61-
for (let j = 0; j < boxSize; j++) {
62-
let ind = j + i * boxSize;
63-
let rotatedPoint = rotatePoint(
64-
Math.floor(boxSize / 2),
65-
Math.floor(boxSize / 2),
66-
-direction,
67-
i,
68-
j
69-
);
70-
let newI = Math.floor(rotatedPoint[0]);
71-
let newJ = Math.floor(rotatedPoint[1]);
72-
let indTile = jBase + newJ + (iBase + newI) * TILE_SIZE;
73-
74-
if (northArrow[4 * ind + 3]) {
75-
rgba[4 * indTile] = 0;
76-
rgba[4 * indTile + 1] = 0;
77-
rgba[4 * indTile + 2] = 0;
78-
rgba[4 * indTile + 3] =
79-
northArrow[4 * ind + 3] * Math.min(((px - 2) / 200) * 50, 100) * (OPACITY / 50);
80-
}
81-
}
82-
}
83-
}
84-
};
23+
// const rotatePoint = (cx: number, cy: number, theta: number, x: number, y: number) => {
24+
// let xt = Math.cos(theta) * (x - cx) - Math.sin(theta) * (y - cy) + cx;
25+
// let yt = Math.sin(theta) * (x - cx) + Math.cos(theta) * (y - cy) + cy;
26+
27+
// return [xt, yt];
28+
// };
29+
30+
// const drawArrow = (
31+
// rgba: Uint8ClampedArray,
32+
// iBase: number,
33+
// jBase: number,
34+
// x: number,
35+
// y: number,
36+
// z: number,
37+
// nx: number,
38+
// domain: Domain,
39+
// projectionGrid: ProjectionGrid,
40+
// values: TypedArray,
41+
// directions: TypedArray,
42+
// boxSize = TILE_SIZE / 8,
43+
// iconPixelData: IconListPixels
44+
// ): void => {
45+
// const northArrow = iconPixelData['0'];
46+
47+
// let iCenter = iBase + Math.floor(boxSize / 2);
48+
// let jCenter = jBase + Math.floor(boxSize / 2);
49+
50+
// const lat = tile2lat(y + iCenter / TILE_SIZE, z);
51+
// const lon = tile2lon(x + jCenter / TILE_SIZE, z);
52+
53+
// const { index, xFraction, yFraction } = getIndexAndFractions(lat, lon, domain, projectionGrid);
54+
55+
// let px = interpolateLinear(values, nx, index, xFraction, yFraction);
56+
57+
// let direction = degreesToRadians(interpolateLinear(directions, nx, index, xFraction, yFraction));
58+
59+
// if (direction) {
60+
// for (let i = 0; i < boxSize; i++) {
61+
// for (let j = 0; j < boxSize; j++) {
62+
// let ind = j + i * boxSize;
63+
// let rotatedPoint = rotatePoint(
64+
// Math.floor(boxSize / 2),
65+
// Math.floor(boxSize / 2),
66+
// -direction,
67+
// i,
68+
// j
69+
// );
70+
// let newI = Math.floor(rotatedPoint[0]);
71+
// let newJ = Math.floor(rotatedPoint[1]);
72+
// let indTile = jBase + newJ + (iBase + newI) * TILE_SIZE;
73+
74+
// if (northArrow[4 * ind + 3]) {
75+
// rgba[4 * indTile] = 0;
76+
// rgba[4 * indTile + 1] = 0;
77+
// rgba[4 * indTile + 2] = 0;
78+
// rgba[4 * indTile + 3] =
79+
// northArrow[4 * ind + 3] * Math.min(((px - 2) / 200) * 50, 100) * (OPACITY / 50);
80+
// }
81+
// }
82+
// }
83+
// }
84+
// };
8585

8686
const getColor = (v: string, px: number): number[] => {
8787
if (v.startsWith('temperature')) {
@@ -219,34 +219,34 @@ self.onmessage = async (message) => {
219219
}
220220
}
221221

222-
if (drawOnTiles.includes(variable.value)) {
223-
const iconPixelData = message.data.iconPixelData;
224-
225-
let reg = new RegExp(/wind_(\d+)m/);
226-
const matches = variable.value.match(reg);
227-
if (matches) {
228-
const boxSize = Math.floor(TILE_SIZE / 16);
229-
for (let i = 0; i < TILE_SIZE; i += boxSize) {
230-
for (let j = 0; j < TILE_SIZE; j += boxSize) {
231-
drawArrow(
232-
rgba,
233-
i,
234-
j,
235-
x,
236-
y,
237-
z,
238-
nx,
239-
domain,
240-
projectionGrid,
241-
values,
242-
directions,
243-
boxSize,
244-
iconPixelData
245-
);
246-
}
247-
}
248-
}
249-
}
222+
// if (drawOnTiles.includes(variable.value)) {
223+
// const iconPixelData = message.data.iconPixelData;
224+
225+
// let reg = new RegExp(/wind_(\d+)m/);
226+
// const matches = variable.value.match(reg);
227+
// if (matches) {
228+
// const boxSize = Math.floor(TILE_SIZE / 16);
229+
// for (let i = 0; i < TILE_SIZE; i += boxSize) {
230+
// for (let j = 0; j < TILE_SIZE; j += boxSize) {
231+
// drawArrow(
232+
// rgba,
233+
// i,
234+
// j,
235+
// x,
236+
// y,
237+
// z,
238+
// nx,
239+
// domain,
240+
// projectionGrid,
241+
// values,
242+
// directions,
243+
// boxSize,
244+
// iconPixelData
245+
// );
246+
// }
247+
// }
248+
// }
249+
// }
250250

251251
const tile = await createImageBitmap(new ImageData(rgba, TILE_SIZE, TILE_SIZE));
252252

vite.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ export default ({ mode }) => {
2929
],
3030
optimizeDeps: {
3131
exclude: ['@openmeteo/file-reader', '@openmeteo/file-format-wasm']
32+
},
33+
server: {
34+
fs: {
35+
// Allow serving files from one level up to the project root
36+
allow: ['..']
37+
}
3238
}
3339
});
3440
};

0 commit comments

Comments
 (0)