• Jump To … +
    ./demo/canvas-001.js ./demo/canvas-002.js ./demo/canvas-003.js ./demo/canvas-004.js ./demo/canvas-005.js ./demo/canvas-006.js ./demo/canvas-007.js ./demo/canvas-008.js ./demo/canvas-009.js ./demo/canvas-010.js ./demo/canvas-011.js ./demo/canvas-012.js ./demo/canvas-013.js ./demo/canvas-014.js ./demo/canvas-015.js ./demo/canvas-016.js ./demo/canvas-017.js ./demo/canvas-018.js ./demo/canvas-019.js ./demo/canvas-020.js ./demo/canvas-021.js ./demo/canvas-022.js ./demo/canvas-023.js ./demo/canvas-024.js ./demo/canvas-025.js ./demo/canvas-026.js ./demo/canvas-027.js ./demo/canvas-028.js ./demo/canvas-029.js ./demo/canvas-030.js ./demo/canvas-031.js ./demo/canvas-032.js ./demo/canvas-033.js ./demo/canvas-034.js ./demo/canvas-035.js ./demo/canvas-036.js ./demo/canvas-037.js ./demo/canvas-038.js ./demo/canvas-039.js ./demo/canvas-040.js ./demo/canvas-041.js ./demo/canvas-042.js ./demo/canvas-043.js ./demo/canvas-044.js ./demo/canvas-045.js ./demo/canvas-046.js ./demo/canvas-047.js ./demo/canvas-048.js ./demo/canvas-049.js ./demo/canvas-050.js ./demo/canvas-051.js ./demo/canvas-052.js ./demo/canvas-053.js ./demo/canvas-054.js ./demo/canvas-055.js ./demo/canvas-056.js ./demo/canvas-057.js ./demo/canvas-058.js ./demo/canvas-059.js ./demo/canvas-060.js ./demo/canvas-061.js ./demo/canvas-062.js ./demo/canvas-063.js ./demo/canvas-064.js ./demo/canvas-065.js ./demo/canvas-066.js ./demo/canvas-067.js ./demo/canvas-068.js ./demo/canvas-069.js ./demo/canvas-070.js ./demo/canvas-071.js ./demo/canvas-072.js ./demo/canvas-073.js ./demo/canvas-201.js ./demo/canvas-202.js ./demo/canvas-203.js ./demo/canvas-204.js ./demo/canvas-205.js ./demo/canvas-206.js ./demo/canvas-207.js ./demo/canvas-208.js ./demo/canvas-209.js ./demo/canvas-210.js ./demo/canvas-211.js ./demo/canvas-212.js ./demo/delaunator-001.js ./demo/delaunator-002.js ./demo/dom-001.js ./demo/dom-002.js ./demo/dom-003.js ./demo/dom-004.js ./demo/dom-005.js ./demo/dom-006.js ./demo/dom-007.js ./demo/dom-008.js ./demo/dom-009.js ./demo/dom-010.js ./demo/dom-011.js ./demo/dom-012.js ./demo/dom-013.js ./demo/dom-015.js ./demo/dom-016.js ./demo/dom-017.js ./demo/dom-018.js ./demo/dom-019.js ./demo/dom-020.js ./demo/dom-021.js ./demo/filters-001.js ./demo/filters-002.js ./demo/filters-003.js ./demo/filters-004.js ./demo/filters-005.js ./demo/filters-006.js ./demo/filters-007.js ./demo/filters-008.js ./demo/filters-009.js ./demo/filters-010.js ./demo/filters-011.js ./demo/filters-012.js ./demo/filters-013.js ./demo/filters-014.js ./demo/filters-015.js ./demo/filters-016.js ./demo/filters-017.js ./demo/filters-018.js ./demo/filters-019.js ./demo/filters-020.js ./demo/filters-021.js ./demo/filters-022.js ./demo/filters-023.js ./demo/filters-024.js ./demo/filters-025.js ./demo/filters-026.js ./demo/filters-027.js ./demo/filters-028.js ./demo/filters-029.js ./demo/filters-030.js ./demo/filters-031.js ./demo/filters-032.js ./demo/filters-033.js ./demo/filters-034.js ./demo/filters-035.js ./demo/filters-036.js ./demo/filters-037.js ./demo/filters-038.js ./demo/filters-039.js ./demo/filters-040.js ./demo/filters-041.js ./demo/filters-042.js ./demo/filters-101.js ./demo/filters-102.js ./demo/filters-103.js ./demo/filters-104.js ./demo/filters-105.js ./demo/filters-501.js ./demo/filters-502.js ./demo/filters-503.js ./demo/filters-504.js ./demo/filters-505.js ./demo/mediapipe-001.js ./demo/mediapipe-002.js ./demo/mediapipe-003.js ./demo/modules-001.js ./demo/modules-002.js ./demo/modules-003.js ./demo/modules-004.js ./demo/modules-005.js ./demo/modules-006.js ./demo/packets-001.js ./demo/packets-002.js ./demo/particles-001.js ./demo/particles-002.js ./demo/particles-003.js ./demo/particles-004.js ./demo/particles-005.js ./demo/particles-006.js ./demo/particles-007.js ./demo/particles-008.js ./demo/particles-009.js ./demo/particles-010.js ./demo/particles-011.js ./demo/particles-012.js ./demo/particles-013.js ./demo/particles-014.js ./demo/particles-015.js ./demo/particles-016.js ./demo/particles-017.js ./demo/snippets-001.js ./demo/snippets-002.js ./demo/snippets-003.js ./demo/snippets-004.js ./demo/snippets-005.js ./demo/snippets-006.js ./demo/temp-001.js ./demo/temp-shape-scale-investigation.js ./demo/tensorflow-001.js ./demo/tensorflow-002.js ./demo/utilities.js
  • §

    Demo Canvas 072

    Public transport furniture cover design

  • §

    Run code

    import * as scrawl from '../source/scrawl.js';
    
    import { reportSpeed } from './utilities.js';
  • §

    Scene setup

    Get a handle to the Canvas wrapper

    const canvas = scrawl.findCanvas('my-canvas');
  • §

    Namespacing boilerplate

    const namespace = canvas.name;
    const name = (n) => `${namespace}-${n}`;
  • §

    Get image from DOM

    scrawl.importDomImage('.image-assets');
  • §

    Create Pattern style using imported image

    scrawl.makePattern({
    
        name: name('weave-pattern'),
        asset: 'weave',
        stretchX: 0.37 / 2.5,
        stretchY: 0.37 / 2.5,
    });
  • §

    Do the work in a dedicated 150 x 100 Cell

    const eWidth = 150,
        eHeight = 100;
    
    const easel = canvas.buildCell({
        name: name('easel-cell'),
        dimensions: [eWidth, eHeight],
        cleared: false,
        compiled: false,
        shown: false
    });
  • §

    Get handles to the Cell’s engine and pixel data

    const easelData = easel.getCellData({
        opaque: true,
        includeGridCoords: false,
        includePolarCoords: false,
    });
    
    const pixelState = easelData.pixelState;
  • §

    Create the display Picture

    scrawl.makeBlock({
        name: name('cloth'),
        dimensions: ['100%', '100%'],
        fillStyle: name('weave-pattern'),
    });
    
    scrawl.makePicture({
        name: name('display'),
        dimensions: ['100%', '100%'],
        copyDimensions: ['100%', '100%'],
        asset: easel,
        imageSmoothingEnabled: false,
        globalAlpha: 0.5,
    });
  • §

    Define the different species

    const empty = {
        name: 'empty',
    };
    
    const species = {
        lightblue: {
            name: 'lightblue',
            isAlive: true,
  • §

    moveX: Math.floor(Math.random() * 7) - 3, moveY: Math.floor(Math.random() * 7) - 3, breedX: Math.floor(Math.random() * 3) - 1, breedY: Math.floor(Math.random() * 3) - 1,

            red: 200,
            green: 200,
            blue: 250
        },
    
        darkblue: {
            name: 'darkblue',
            isAlive: true,
  • §

    moveX: Math.floor(Math.random() * 7) - 3, moveY: Math.floor(Math.random() * 7) - 3, breedX: Math.floor(Math.random() * 3) - 1, breedY: Math.floor(Math.random() * 3) - 1,

            red: 20,
            green: 20,
            blue: 150
        },
    };
    
    const speciesNames = Object.keys(species);
  • §

    Create the beasts

    const beasts = [];
  • §

    Create the landscape array

    const landscape = new Array(eHeight * eWidth).fill(empty);
    
    
    const initialize = () => {
    
        render.halt();
    
        beasts.length = 0;
        landscape.fill(empty);
    
        speciesNames.forEach(label => {
    
            const s = species[label];
    
            s.moveX = Math.floor(Math.random() * 7) - 3;
            s.moveY = Math.floor(Math.random() * 7) - 3;
            s.breedX = Math.floor(Math.random() * 3) - 1;
            s.breedY = Math.floor(Math.random() * 3) - 1;
        });
    
        for (let i = 0; i < 50; i++) {
    
            const x = Math.floor(Math.random() * eWidth),
                y = Math.floor(Math.random() * eHeight),
                index = y * eWidth + x;
    
            if (landscape[index].name === 'empty') {
    
                const egg = Math.floor(Math.random() * speciesNames.length);
    
                const baby = Object.assign({}, species[speciesNames[egg]]);
    
                baby.currentX = x;
                baby.currentY = y;
                baby.currentIndex = index;
    
                beasts.push(baby);
                landscape[index] = baby;
            }
        }
        counter = 0;
        generations = 0;
    
        finalize();
    
        render.run();
    };
  • §

    Beast functionality - movement

    const move = () => {
    
        beasts.forEach((beast) => {
    
            const { currentX, currentY, moveX, moveY } = beast;
    
            let nextX = currentX + moveX,
                nextY = currentY + moveY;
    
            if (nextX >= eWidth) nextX -= eWidth;
            else if (nextX < 0) nextX += eWidth;
    
            if (nextY >= eHeight) nextY -= eHeight;
            else if (nextY < 0) nextY += eHeight;
    
            const nextIndex = nextY * eWidth + nextX;
    
            if (landscape[nextIndex].name === 'empty') {
    
                beast.currentX = nextX;
                beast.currentY = nextY;
                beast.currentIndex = nextIndex;
    
                landscape[nextIndex] = beast;
            }
            else {
    
                beast.isAlive = false;
                landscape[nextIndex].isAlive = false;
            }
        });
    };
  • §

    Beast functionality - breeding

    const breed = () => {
    
        beasts.forEach((beast) => {
    
            const { currentX, currentY, breedX, breedY } = beast;
    
            let nextX = currentX + breedX,
                nextY = currentY + breedY;
    
            if (nextX >= eWidth) nextX -= eWidth;
            else if (nextX < 0) nextX += eWidth;
    
            if (nextY >= eHeight) nextY -= eHeight;
            else if (nextY < 0) nextY += eHeight;
    
            const nextIndex = nextY * eWidth + nextX;
    
            if (landscape[nextIndex].name === 'empty') {
    
                const egg = Math.floor(Math.random() * speciesNames.length);
    
                const baby = Object.assign({}, species[speciesNames[egg]]);
    
                baby.currentX = nextX;
                baby.currentY = nextY;
                baby.currentIndex = nextIndex;
    
                beasts.push(baby);
                landscape[nextIndex] = baby;
            }
        });
    };
  • §

    Transfer data to pixel objects

    const finalize = () => {
    
        const tempBeasts = beasts.filter((beast) => beast.isAlive);
    
        beasts.length = 0;
        beasts.push(...tempBeasts);
    
        beasts.forEach((beast) => {
    
            const p = pixelState[beast.currentIndex];
    
            p.red = beast.red;
            p.green = beast.green;
            p.blue = beast.blue;
        });
    };
  • §

    Update once every Display cycle, with added choke and stop

    const counterChoke = 3,
        generationsChoke = 40;
    
    let counter = 0,
        generations = 0;
    
    const update = () => {
    
        if (generations < generationsChoke) {
    
            counter++;
    
            if (counter >= counterChoke) {
    
                counter = 0;
                generations++;
    
                pixelState.forEach(p => {
    
                    p.red = 200;
                    p.green = 0;
                    p.blue = 0;
                });
    
                landscape.fill(empty);
    
                move();
                breed();
                finalize();
    
                easel.paintCellData(easelData);
            }
        }
    };
  • §

    Scene animation

    Function to display frames-per-second data, and other information relevant to the demo

    const report = reportSpeed('#reportmessage');
  • §

    Create the Display cycle animation

    const render = scrawl.makeRender({
    
        name: name('animation'),
        target: canvas,
        commence: update,
        afterShow: report,
    });
  • §

    Start run

    initialize();
  • §

    User interaction

    scrawl.addNativeListener('click', initialize, canvas.domElement);
  • §

    Development and testing

    console.log(scrawl.library);