Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added src/assets/intro/0000.avif
Binary file not shown.
Binary file removed src/assets/intro/0000.webp
Binary file not shown.
Binary file added src/assets/intro/0001.avif
Binary file not shown.
Binary file removed src/assets/intro/0001.webp
Binary file not shown.
Binary file added src/assets/intro/0002.avif
Binary file not shown.
Binary file removed src/assets/intro/0002.webp
Binary file not shown.
Binary file added src/assets/intro/0003.avif
Binary file not shown.
Binary file removed src/assets/intro/0003.webp
Binary file not shown.
Binary file added src/assets/intro/0004.avif
Binary file not shown.
Binary file removed src/assets/intro/0004.webp
Binary file not shown.
Binary file added src/assets/intro/0005.avif
Binary file not shown.
Binary file removed src/assets/intro/0005.webp
Binary file not shown.
Binary file added src/assets/intro/0006.avif
Binary file not shown.
Binary file removed src/assets/intro/0006.webp
Binary file not shown.
Binary file added src/assets/intro/0007.avif
Binary file not shown.
Binary file removed src/assets/intro/0007.webp
Binary file not shown.
Binary file added src/assets/intro/0008.avif
Binary file not shown.
Binary file removed src/assets/intro/0008.webp
Binary file not shown.
Binary file added src/assets/intro/0009.avif
Binary file not shown.
Binary file removed src/assets/intro/0009.webp
Binary file not shown.
Binary file added src/assets/intro/0010.avif
Binary file not shown.
Binary file removed src/assets/intro/0010.webp
Binary file not shown.
Binary file added src/assets/intro/0011.avif
Binary file not shown.
Binary file removed src/assets/intro/0011.webp
Binary file not shown.
Binary file added src/assets/intro/0012.avif
Binary file not shown.
Binary file removed src/assets/intro/0012.webp
Binary file not shown.
Binary file added src/assets/intro/0013.avif
Binary file not shown.
Binary file removed src/assets/intro/0013.webp
Binary file not shown.
Binary file added src/assets/intro/0014.avif
Binary file not shown.
Binary file removed src/assets/intro/0014.webp
Binary file not shown.
Binary file added src/assets/intro/0015.avif
Binary file not shown.
Binary file removed src/assets/intro/0015.webp
Binary file not shown.
Binary file added src/assets/intro/0016.avif
Binary file not shown.
Binary file removed src/assets/intro/0016.webp
Binary file not shown.
Binary file added src/assets/intro/0017.avif
Binary file not shown.
Binary file removed src/assets/intro/0017.webp
Binary file not shown.
Binary file added src/assets/intro/0018.avif
Binary file not shown.
Binary file removed src/assets/intro/0018.webp
Binary file not shown.
Binary file added src/assets/intro/0019.avif
Binary file not shown.
Binary file removed src/assets/intro/0019.webp
Binary file not shown.
Binary file added src/assets/intro/0020.avif
Binary file not shown.
Binary file removed src/assets/intro/0020.webp
Binary file not shown.
Binary file added src/assets/intro/0021.avif
Binary file not shown.
Binary file removed src/assets/intro/0021.webp
Binary file not shown.
Binary file added src/assets/intro/0022.avif
Binary file not shown.
Binary file removed src/assets/intro/0022.webp
Binary file not shown.
Binary file added src/assets/intro/0023.avif
Binary file not shown.
Binary file removed src/assets/intro/0023.webp
Binary file not shown.
Binary file added src/assets/intro/0024.avif
Binary file not shown.
Binary file removed src/assets/intro/0024.webp
Binary file not shown.
Binary file added src/assets/intro/0025.avif
Binary file not shown.
Binary file removed src/assets/intro/0025.webp
Diff not rendered.
Binary file added src/assets/intro/0026.avif
Binary file not shown.
Binary file removed src/assets/intro/0026.webp
Diff not rendered.
Binary file added src/assets/intro/0027.avif
Binary file not shown.
Binary file removed src/assets/intro/0027.webp
Diff not rendered.
Binary file added src/assets/intro/0028.avif
Binary file not shown.
Binary file removed src/assets/intro/0028.webp
Diff not rendered.
Binary file added src/assets/intro/0029.avif
Binary file not shown.
Binary file removed src/assets/intro/0029.webp
Diff not rendered.
Binary file added src/assets/intro/0030.avif
Binary file not shown.
Binary file removed src/assets/intro/0030.webp
Diff not rendered.
Binary file added src/assets/intro/0031.avif
Binary file not shown.
Binary file removed src/assets/intro/0031.webp
Diff not rendered.
Binary file added src/assets/intro/0032.avif
Binary file not shown.
Binary file removed src/assets/intro/0032.webp
Diff not rendered.
Binary file added src/assets/intro/0033.avif
Binary file not shown.
Binary file removed src/assets/intro/0033.webp
Diff not rendered.
Binary file added src/assets/intro/0034.avif
Binary file not shown.
Binary file removed src/assets/intro/0034.webp
Diff not rendered.
Binary file added src/assets/intro/0035.avif
Binary file not shown.
Binary file removed src/assets/intro/0035.webp
Diff not rendered.
Binary file added src/assets/intro/0036.avif
Binary file not shown.
Binary file removed src/assets/intro/0036.webp
Diff not rendered.
Binary file added src/assets/intro/0037.avif
Binary file not shown.
Binary file removed src/assets/intro/0037.webp
Diff not rendered.
Binary file added src/assets/intro/0038.avif
Binary file not shown.
Binary file removed src/assets/intro/0038.webp
Diff not rendered.
Binary file added src/assets/intro/0039.avif
Binary file not shown.
Binary file removed src/assets/intro/0039.webp
Diff not rendered.
Binary file added src/assets/intro/0040.avif
Binary file not shown.
Binary file removed src/assets/intro/0040.webp
Diff not rendered.
Binary file added src/assets/intro/0041.avif
Binary file not shown.
Binary file removed src/assets/intro/0041.webp
Diff not rendered.
Binary file added src/assets/intro/0042.avif
Binary file not shown.
Binary file removed src/assets/intro/0042.webp
Diff not rendered.
Binary file added src/assets/intro/0043.avif
Binary file not shown.
Binary file removed src/assets/intro/0043.webp
Diff not rendered.
Binary file added src/assets/intro/0044.avif
Binary file not shown.
Binary file removed src/assets/intro/0044.webp
Diff not rendered.
Binary file added src/assets/intro/0045.avif
Binary file not shown.
Binary file removed src/assets/intro/0045.webp
Diff not rendered.
Binary file added src/assets/intro/0046.avif
Binary file not shown.
Binary file removed src/assets/intro/0046.webp
Diff not rendered.
Binary file added src/assets/intro/0047.avif
Binary file not shown.
Binary file removed src/assets/intro/0047.webp
Diff not rendered.
Binary file added src/assets/intro/0048.avif
Binary file not shown.
Binary file removed src/assets/intro/0048.webp
Diff not rendered.
Binary file added src/assets/intro/0049.avif
Binary file not shown.
Binary file removed src/assets/intro/0049.webp
Diff not rendered.
Binary file added src/assets/intro/0050.avif
Binary file not shown.
Binary file removed src/assets/intro/0050.webp
Diff not rendered.
Binary file added src/assets/intro/0051.avif
Binary file not shown.
Binary file removed src/assets/intro/0051.webp
Diff not rendered.
Binary file added src/assets/intro/0052.avif
Binary file not shown.
Binary file removed src/assets/intro/0052.webp
Diff not rendered.
Binary file added src/assets/intro/0053.avif
Binary file not shown.
Binary file removed src/assets/intro/0053.webp
Diff not rendered.
Binary file added src/assets/intro/0054.avif
Binary file not shown.
Binary file removed src/assets/intro/0054.webp
Diff not rendered.
Binary file added src/assets/intro/0055.avif
Binary file not shown.
Binary file removed src/assets/intro/0055.webp
Diff not rendered.
Binary file added src/assets/intro/0056.avif
Binary file not shown.
Binary file removed src/assets/intro/0056.webp
Diff not rendered.
Binary file added src/assets/intro/0057.avif
Binary file not shown.
Binary file removed src/assets/intro/0057.webp
Diff not rendered.
Binary file added src/assets/intro/0058.avif
Binary file not shown.
Binary file removed src/assets/intro/0058.webp
Diff not rendered.
Binary file added src/assets/intro/0059.avif
Binary file not shown.
Binary file removed src/assets/intro/0059.webp
Diff not rendered.
Binary file added src/assets/intro/0060.avif
Binary file not shown.
Binary file removed src/assets/intro/0060.webp
Diff not rendered.
53 changes: 53 additions & 0 deletions src/components/Graphics.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
import type GraphicsImporter from "../scripts/graphics-importer";
interface Props {
graphicsImporter: GraphicsImporter;
alt: string;
}

const { graphicsImporter, alt } = Astro.props;
---
{graphicsImporter.getImageSrcs().then((srcs) => (
<!--suppress HtmlUnknownTag -->
<graphics-element data-srcs={JSON.stringify(srcs)}>
{
graphicsImporter.getFirstImageMetadata().then(({default: {src, width, height}}) => (
<img id="intro-graphics" class="max-w-full" src={src} width={width} height={height}
alt={alt}/>
))
}
</graphics-element>
))}

<script>
class Graphics extends HTMLElement {
connectedCallback() {
const imageSrcs = JSON.parse(this.dataset.srcs ?? "[]");
const outputImage = this.querySelector("img") ?? (() => {
throw new Error("Failed to get output image element");
})();

// Collect components.
const containerBounds =
outputImage.parentElement?.parentElement?.getBoundingClientRect() ??
(() => {
throw new Error("Failed to get canvas containing element and bounds");
})();
const numberOfImages = imageSrcs.length;

// Bind scroll event to draw images.
window.addEventListener("scroll", () => {
const scrollFraction =
(document.documentElement.scrollTop - containerBounds.top) /
(containerBounds.bottom - containerBounds.top);
const imageIndex = Math.min(
numberOfImages - 1,
Math.ceil(scrollFraction * numberOfImages),
);
requestAnimationFrame(() => outputImage.src = imageSrcs[Math.max(0, Math.min(imageIndex, numberOfImages - 1))]);
});
}
}

customElements.define("graphics-element", Graphics);
</script>
30 changes: 20 additions & 10 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
---
interface Props {
imageSrcs: Promise<string[]>;
}

const { imageSrcs } = Astro.props;
---
<!doctype html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico"/>
<meta name="generator" content={Astro.generator} />
<title>Pinpoint</title>
</head>
<body>
<slot />
</body>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width"/>
<link rel="icon" type="image/svg+xml" href="/favicon.ico"/>
<meta name="generator" content={Astro.generator}/>
<title>Pinpoint</title>

<!-- Preload images. -->
{imageSrcs.then((srcs) => srcs.map((src) => (
<link rel="preload" href={src} as="image" type="image/avif"/>
)))}
</head>
<body>
<slot/>
</body>
</html>
20 changes: 11 additions & 9 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@
import Article from "../components/Article.astro";
import Hero from "../components/Hero.astro";
import Layout from "../layouts/Layout.astro";

import Graphics from "../components/Graphics.astro";
import GraphicsImporter from "../scripts/graphics-importer";
import type { DefaultImageMetadata } from "../scripts/types";

const introImporter = new GraphicsImporter(
import.meta.glob<DefaultImageMetadata>("/src/assets/intro/*.avif"),
);
---

<Layout>
<Layout imageSrcs={introImporter.getImageSrcs()}>
<!-- Pinpoint Intro Sequence. -->
<div class="hero">
<div class="hero-content flex-col lg:flex-row-reverse w-full">
<!-- Graphics side. -->
<div class="basis-1/2 self-stretch">
<div class="h-dvh sticky top-0 flex justify-center items-center">
<canvas id="intro-graphics" class="max-w-full aspect-3/4"/>
<Graphics graphicsImporter={introImporter} alt="Pinpoint intro sequence"/>
</div>
</div>

Expand Down Expand Up @@ -116,10 +124,4 @@ import Layout from "../layouts/Layout.astro";
margin-top: -45dvh;
visibility: hidden;
}
</style>

<script>
import GraphicsDrawer from "../scripts/graphics-drawer.ts";

new GraphicsDrawer(import.meta.glob<{ default: ImageMetadata }>("/src/assets/intro/*.webp"), "intro-graphics");
</script>
</style>
105 changes: 0 additions & 105 deletions src/scripts/graphics-drawer.ts

This file was deleted.

39 changes: 39 additions & 0 deletions src/scripts/graphics-importer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { DefaultImageMetadata } from "./types.ts";

/**
* Imports graphics from source folder and provides their resolved URLs.
*/
export default class GraphicsImporter {
// Fields.
private readonly imageMetadatas: Promise<DefaultImageMetadata>[];

/**
* Extract image metadata from dynamic import.
* @param imageDynamicImport Dynamic import of images.
*/
constructor(
imageDynamicImport: Record<string, () => Promise<DefaultImageMetadata>>,
) {
this.imageMetadatas = Object.values(imageDynamicImport).map((imageImport) =>
imageImport(),
);
}

/**
* Get the source URLs of all images.
*/
async getImageSrcs(): Promise<string[]> {
return Promise.all(
this.imageMetadatas.map((imageMetadataPromise) =>
imageMetadataPromise.then(({ default: { src } }) => src),
),
);
}

/**
* Get the metadata of the first image.
*/
async getFirstImageMetadata(): Promise<DefaultImageMetadata> {
return await this.imageMetadatas[0];
}
}
1 change: 1 addition & 0 deletions src/scripts/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type DefaultImageMetadata = { default: ImageMetadata };