# Canvas placement

> Where the game sits in its page: where align says, if the game says; otherwise where the page asks with flex or grid, or in the middle.

Example `canvas-placement`, running at https://nacatamalon.com/en/examples/canvas-placement. The whole catalogue: https://nacatamalon.com/llms/examples.md.

Each box is a page of its own, with the same game in it: 56 × 32 at `scaling: 'integer'`. Where it goes only moves the space left over: the game is the same size.

The game can say where with `align` (`SCREEN.ALIGN.TOP`, `BOTTOM_RIGHT`…), and then it wins over the page. When it says nothing, the page decides: a page that lays its content out itself, with flex or grid, puts the game where it aligns it, and a page that says nothing has it in the middle both ways. Padding is room the game does not take.

## Code

`index.ts`:

```ts
import { mountPages } from './host/layout';

mountPages(document.querySelector<HTMLElement>('#app')!);
```

`host/layout.ts`:

```ts
import { createGame } from 'nacatamalon';

import * as Settings from '../settings';
import { Level } from '../scenes/demo';

export const mountPages = (app: HTMLElement) => {
    const sheet = document.createElement('div');

    Object.assign(sheet.style, {
        display: 'grid',
        gridTemplateColumns: 'repeat(3, 150px)',
        gap: '14px',
        font: '11px monospace',
        color: '#9aa3c7'
    });
    app.append(sheet);

    for (const page of Settings.PAGES) {
        const cell = document.createElement('div');
        const label = document.createElement('div');

        label.textContent = page.label;
        // Room for two lines, so the boxes of a row start at the same height.
        Object.assign(label.style, {
            height: '28px',
            lineHeight: '14px',
            marginBottom: '4px'
        });

        // The page: outlined, so where the game sits in it can be seen.
        const box = document.createElement('div');

        Object.assign(box.style, {
            width: '150px',
            height: '96px',
            outline: '1px solid #33e0ff',
            background: '#0a0a14',
            ...page.css
        });
        cell.append(label, box);
        sheet.append(cell);

        const game = createGame(box, {
            width: Settings.WIDTH,
            height: Settings.HEIGHT,
            scaling: 'integer',
            align: page.align,
            background: '#c0392b'
        });

        // Declare Scenes
        game({
            Level
        });
    }
};
```

`scenes/demo.ts`:

```ts
import { createScene, createText } from 'nacatamalon';

export const Level = () => {
    createText({
        text: 'GAME',
        anchor: {
            x: 0.5,
            y: 0.5
        },
        transform: {
            x: 28,
            y: 16
        }
    });

    return createScene();
};
```

`settings.ts`:

```ts
import { SCREEN } from 'nacatamalon';
import type { TCanvasAlign } from 'nacatamalon';

export const WIDTH = 56;
export const HEIGHT = 32;
export const PAGES: Array<{ label: string; css: Partial<CSSStyleDeclaration>; align?: TCanvasAlign; }> = [
    {
        label: 'page says nothing',
        css: {
        }
    },
    {
        label: 'flex · center',
        css: {
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center'
        }
    },
    {
        label: 'flex · flex-start',
        css: {
            display: 'flex',
            justifyContent: 'flex-start',
            alignItems: 'flex-start'
        }
    },
    {
        label: 'flex · flex-end',
        css: {
            display: 'flex',
            justifyContent: 'flex-end',
            alignItems: 'flex-end'
        }
    },
    {
        label: 'grid · place-items: center',
        css: {
            display: 'grid',
            placeItems: 'center'
        }
    },
    {
        label: 'flex · center, padding 24px',
        css: {
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            padding: '24px',
            boxSizing: 'border-box'
        }
    },
    {
        label: 'game: align BOTTOM_RIGHT',
        css: {
        },
        align: SCREEN.ALIGN.BOTTOM_RIGHT
    },
    // The page asks for the top-left corner, and the game for the middle: the game wins.
    {
        label: 'flex-start, game: align CENTER',
        css: {
            display: 'flex',
            justifyContent: 'flex-start',
            alignItems: 'flex-start'
        },
        align: SCREEN.ALIGN.CENTER
    },
];
```
