# Sådan lægger du primo-pakke ind på siden

Pakken er statiske filer og én afspiller uden afhængigheder. Der er ikke noget
byggetrin, ingen pakkemanager og ingen server, der skal køre noget: læg mappen,
hvor siden serverer sine billeder fra, og peg på den.

Tallene herunder er den her pakkes egne, så eksemplerne kan kopieres, som de
står. Skift kun stien.

- Billeder i sekvensen: 94
- Største udgave: 1280 × 720 px
- Filtype: image/webp
- Scroll-længde: 300 vh
- Mobiludgave: 720 × 404 px under 768 px

## 1. Læg mappen på serveren

Hele mappen, som den er, med de samme filnavne. Afspilleren regner navnene ud
af mønsteret i `manifest.json` (`frame-{index:4}.webp`), så et enkelt
omdøbt billede er et hul i animationen.

```
assets/primo-pakke/
  frames-desktop/
  frames-mobile/
  fallback/
  scroll-animation.js
  scroll-animation.css
  manifest.json
```

## 2. Ren html

To linjer i `<head>` og en `<div>`, hvor animationen skal stå.

```html
<link rel="stylesheet" href="/assets/primo-pakke/scroll-animation.css">

<div data-motion="/assets/primo-pakke/" data-motion-label="primo-pakke"></div>

<script src="/assets/primo-pakke/scroll-animation.js" defer></script>
```

`data-motion` peger på mappen med `manifest.json`. Alt andet, antal billeder,
mål, udgaver og scroll-længde, står i manifestet.

## 3. React eller Next.js

Afspilleren skal køre i browseren og først, når elementet står i dokumentet.

```jsx
"use client";

import { useEffect, useRef } from "react";

const BASE = "/assets/primo-pakke/";

export function ScrollAnimation({ label = "primo-pakke" }) {
  const holder = useRef(null);

  useEffect(() => {
    let stop = () => {};

    // Afspilleren starter sig selv, når scriptet hentes, men i React kommer
    // og går elementet. Derfor startes den på elementet, og stoppes igen,
    // når komponenten forsvinder: ellers kører tegneløkken videre på noget,
    // ingen kan se.
    const start = () => {
      if (holder.current) stop = window.SqueezeitMotion.boot(holder.current);
    };

    if (window.SqueezeitMotion) {
      start();
    } else {
      const script = document.createElement("script");
      script.src = BASE + "scroll-animation.js";
      script.async = true;
      script.onload = start;
      document.body.appendChild(script);
    }

    return () => stop();
  }, []);

  return <div ref={holder} data-motion={BASE} data-motion-label={label} />;
}
```

Stilarket lægges ind én gang, enten i `app/layout.tsx` med et `<link>` eller
ved at kopiere `scroll-animation.css` ind i sidens eget stilark.

I Next.js hører mappen til i `public/`, og så er stien `/assets/primo-pakke/` uden
`public` i. Ligger siden under et grundpræfiks, skal det med.

## 4. WordPress

Læg mappen i temaets mappe, og hent de to filer i `functions.php`:

```php
add_action('wp_enqueue_scripts', function () {
  $base = get_stylesheet_directory_uri() . '/motion/';
  wp_enqueue_style('motion', $base . 'scroll-animation.css', [], '1');
  wp_enqueue_script('motion', $base . 'scroll-animation.js', [], '1', true);
});
```

Og i skabelonen eller en html-blok:

```html
<div data-motion="/wp-content/themes/DIT-TEMA/motion/"></div>
```

## 5. Shopify

Filerne i `assets/` (Shopify tillader ikke undermapper der, så billederne skal
ligge et sted, der gør: en fil pr. billede i `assets/` med navnet bevaret, eller
hele mappen på et cdn, du selv styrer). Derefter i sektionen:

```liquid
{{ 'scroll-animation.css' | asset_url | stylesheet_tag }}
<div data-motion="{{ 'manifest.json' | asset_url | split: 'manifest.json' | first }}"></div>
{{ 'scroll-animation.js' | asset_url | script_tag }}
```

## Cache og hastighed

Billederne er uforanderlige: skifter sekvensen, kommer der en ny mappe. Så de
kan caches så længe, serveren gider:

```
Cache-Control: public, max-age=31536000, immutable
```

`manifest.json` skal derimod kunne skiftes ud, så den får en kort levetid:

```
Cache-Control: public, max-age=300
```

Afspilleren henter selv kun det, der skal bruges: første billede med det samme,
derefter en lille bølge omkring dét, der vises nu. Der hentes ikke
94 filer på én gang.

## Fejlfinding

- **Intet sker, og der står `data-motion-error` på elementet.** Stien i
  `data-motion` peger ikke på mappen med `manifest.json`. Den skal være
  absolut fra sidens rod eller relativ til den side, der viser den.
- **Første billede vises, men der sker ikke mere.** Elementet har ingen højde.
  Det får sin højde af afspilleren (300 vh), medmindre noget
  andet i sidens css tvinger `height` eller `overflow` på det.
- **Billederne kommer ikke.** Se i netværksfanen, om filerne serveres med den
  rigtige type (`image/webp`). Nogle servere kender ikke webp
  som standard og skal have den skrevet ind.
- **Animationen står stille for nogen.** Sådan skal det være, hvis de har slået
  bevægelse fra i styresystemet. Så vises første billede, og siden virker.
