Skip to content

Commit

Permalink
Client/feature/animated tile layer (#47)
Browse files Browse the repository at this point in the history
* Update mapbox version

* Refactor animated tile layer to be used with deck-json-layer

* Add env variables for mapbox username and style id
  • Loading branch information
barbara-chaves authored Feb 6, 2024
1 parent 24f228e commit 9bfe7e0
Show file tree
Hide file tree
Showing 33 changed files with 538 additions and 460 deletions.
27 changes: 27 additions & 0 deletions client/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Public url. Canonical url of the project.
NEXT_PUBLIC_URL=

# Environment. Only for development. It will be provided by Vercel otherwise.
NEXT_PUBLIC_ENVIRONMENT=

# API Url.
# Development, Preview, Production
# Depending on the environment we will use different urls. It can be the same for the storybook and for the project.
NEXT_PUBLIC_API_URL=
NEXT_PUBLIC_BASE_PATH=
NEXT_PUBLIC_PREVIEW_SECRET=
# Mapbox token
# Development, Preview, Production
# corresponding to the account used for this project. It can be the same for the storybook and for the project.
NEXT_PUBLIC_MAPBOX_API_TOKEN=
NEXT_PUBLIC_MAPBOX_USERNAME=
NEXT_PUBLIC_MAPBOX_STYLE_ID=

# Google Analytics tracking ID.
# Development, Preview, Production
# If you're working with an Google Analytics 4 property, you have a Measurement ID instead of a Tracking ID.
NEXT_PUBLIC_GA_TRACKING_ID=

# Recoil: Remove warnings about duplicate atoms due to hot-reloading
# Development
RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED=false
1 change: 1 addition & 0 deletions client/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const nextConfig = {
process.env.NEXT_PUBLIC_API_URL,
'esa-gda-comms-staging-cms.fra1.digitaloceanspaces.com',
'fra1.digitaloceanspaces.com',
'esa-gda-comms-staging-mfafc.ondigitalocean.app',
],
},
env: {
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"eslint-config-next": "13.4.5",
"framer-motion": "^10.16.4",
"lucide-react": "^0.252.0",
"mapbox-gl": "2.15.0",
"mapbox-gl": "^3.0.1",
"next": "13.4.5",
"postcss": "8.4.24",
"react": "18.2.0",
Expand Down
217 changes: 0 additions & 217 deletions client/src/components/map/layers/animated-tile-layer/index.tsx

This file was deleted.

89 changes: 89 additions & 0 deletions client/src/components/map/layers/animated-tile/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { TileLayer } from '@deck.gl/geo-layers';
import { BitmapLayer } from '@deck.gl/layers';
import parseAPNG from 'apng-js';
import { RasterSource } from 'mapbox-gl';

import { LayerProps } from '@/types/layers';

export interface AnimatedTileProps extends LayerProps {
source: RasterSource;
opacity: number;
visibility: boolean;
beforeId: string;
decodeFunction: string;
decodeParams: Record<string, unknown>;
frame: number;
}

export class AnimatedTile {
constructor({ id, source, visibility = true, opacity = 1, frame = 0 }: AnimatedTileProps) {
return new TileLayer({
id,
frame,
tileSize: source.tileSize ?? 256,
minZoom: source.minzoom,
maxZoom: source.maxzoom,
visible: visibility ?? true,
opacity: opacity ?? 1,
refinementStrategy: 'no-overlap',
getTileData: (tile: any) => {
const {
index: { x, y, z },
signal,
} = tile;
if (!source.url) return null;
const tileUrl = source.url.replace('{z}', z).replace('{x}', x).replace('{y}', y);

const response = fetch(tileUrl, { signal });

if (signal.aborted) {
return null;
}

return response
.then((res) => res.arrayBuffer())
.then((buffer) => {
const apng = parseAPNG(buffer);
if (apng instanceof Error) {
return null;
}
return apng.frames.map((f: any) => {
return {
...f,
bitmapData: createImageBitmap(f.imageData),
};
});
});
},
renderSubLayers: (sl: any) => {
if (!sl) return null;

const { id: subLayerId, data, tile, visible, opacity = 1, frame: f } = sl;

if (!tile || !data) return null;

const {
zoom,
bbox: { west, south, east, north },
} = tile;

const FRAME = data[f];

if (FRAME) {
return new BitmapLayer({
id: subLayerId,
image: FRAME.bitmapData,
bounds: [west, south, east, north],
getPolygonOffset: () => {
return [0, 20000];
},
zoom,
visible,
opacity,
});
}
return null;
},
});
}
}
7 changes: 6 additions & 1 deletion client/src/components/map/layers/deck-json-layer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ const DeckJsonLayer = <T,>({ id, config }: DeckJsonLayerProps<T>) => {
const { addLayer, removeLayer } = useDeckMapboxOverlayContext();

useEffect(() => {
addLayer(config.clone({ id: i, beforeId: id }));
const timeout = setTimeout(() => {
addLayer(config.clone({ id: i, beforeId: id }));
}, 10);
return () => {
clearTimeout(timeout);
};
}, [i, id, config, addLayer]);

useEffect(() => {
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/map/legend/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ export const Legend: React.FC<LegendProps> = ({
return (
<div
className={cn({
'relative flex grow flex-col overflow-hidden': true,
'relative flex-col overflow-hidden': true,
hidden: !isChildren,
[className]: !!className,
})}
>
{isChildren && (
<div className="relative flex h-full flex-col overflow-hidden">
<div className="overflow-y-auto overflow-x-hidden">
<div className="flex items-end gap-4 overflow-y-auto overflow-x-hidden">
{!!sortable.enabled && !!onChangeOrder && (
<SortableList sortable={sortable} onChangeOrder={onChangeOrder}>
{children}
</SortableList>
)}

{!sortable.enabled && children}
{children}
</div>
</div>
)}
Expand Down
Loading

0 comments on commit 9bfe7e0

Please sign in to comment.