• 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 DOM 008

    3d animated cube

    To note: this demo includes an edge case where each canvas has a shadow dot which will track the mouse cursor, but only while the cursor is moving and happens to be over the canvas. When the cursor is stationary the shadow dot will not move even though the canvas itself has rotated

    • This is because each canvas is using a local here object, which better tracks mouse positions over the rotated canvas
    • This local here is gets updated by an event listener attached to the canvas DOM element listening for mouse/pointer/touch movements over it
    • An alternative to this approach is to use the regular here functionality to determine current mouse position and rotate the results (using quaternions) to match each canvas element’s current 3d rotation, recalculating every time the mouse moves or the canvas rotates.
    • (There may be alternative, better solutions but we can’t think of any at the moment)
    • The current solution is computationally cheap (the browser does it for us) but, in this particular edge case, unsatisfactory
    • Action: we could do the work, but only if someone comes up with a compelling reason to do it! For now, mark as “won’t fix”
  • §

    Run code

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

    Scene setup

    Convenience labels - to save some typing

    const stack = scrawl.findStack('mystack');
  • §

    Namespacing boilerplate

    const namespace = stack.name;
    const name = (n) => `${namespace}-${n}`;
    
    
    const pin = scrawl.findElement('pin'),
        front = scrawl.findCanvas('frontface'),
        back = scrawl.findCanvas('backface'),
        top = scrawl.findCanvas('topface'),
        bottom = scrawl.findCanvas('bottomface'),
        left = scrawl.findCanvas('leftface'),
        right = scrawl.findCanvas('rightface');
    
    const faces = scrawl.makeGroup({
    
        name: name('faces'),
    
    }).addArtefacts(left, right, top, bottom, front, back);
    
    stack.set({
        perspectiveX: '50%',
        perspectiveY: '50%',
        perspectiveZ: 1000,
    });
    
    pin.set({
        order: 1,
        width: 0,
        height: 0,
        start: ['center', 'center'],
        lockTo: 'start',
  • §

    To spin the cube we only need to rotate this element

    • canvases pivot to the cube element for position/rotation
        delta: {
            pitch: 0.4,
            yaw: 0.8,
            roll: 0.2,
        }
    });
  • §

    Give our canvases some common values, via their Group

    faces.setArtefacts({
  • §

    Make sure the canvases get processed after the pin

    • so that they pick up changes to its positioning
        order: 2,
    
        start: ['center', 'center'],
        handle: ['center', 'center'],
  • §

    Offset each canvas from the pin

        offsetZ: 150,
        trackHere: 'local',
  • §

    Set each canvas to pivot to the pin

        lockTo: 'pivot',
        pivot: pin,
  • §

    Automatically add the pin’s rotation values to each canvas’s initial rotation value (set below)

        addPivotRotation: true,
  • §

    Styling common to all the canvas elements

        css: { backfaceVisibility: 'hidden' },
    });
  • §

    Give each canvas its initial rotation

    right.set({ yaw: 90 });
    top.set({ pitch: 90 });
    back.set({ pitch: 180 });
    left.set({ yaw: 270 });
    bottom.set({ pitch: 270 });
  • §

    Build some gradients to color the canvases

    scrawl.makeGradient({
    
        name: name('red-gradient'),
        endX: '100%',
        endY: '100%',
        colors: [
            [0, '#f88'],
            [499, '#f00'],
            [999, '#800'],
        ],
        colorSpace: 'OKLAB',
    
    }).clone({
    
        name: name('green-gradient'),
        colors: [
            [0, '#8f8'],
            [499, '#0f0'],
            [999, '#080'],
        ]
    
    }).clone({
    
        name: name('blue-gradient'),
        colors: [
            [0, '#aaf'],
            [499, '#66f'],
            [999, '#66a'],
        ]
    
    }).clone({
    
        name: name('yellow-gradient'),
        colors: [
            [0, '#ff8'],
            [499, '#ff0'],
            [999, '#880'],
        ]
    
    }).clone({
    
        name: name('magenta-gradient'),
        colors: [
            [0, '#f8f'],
            [499, '#f0f'],
            [999, '#808'],
        ]
    
    }).clone({
    
        name: name('cyan-gradient'),
        colors: [
            [0, '#8ff'],
            [499, '#0ff'],
            [999, '#088'],
        ]
    });
  • §

    Display a gradient on each canvas using a Block entity

    scrawl.makeBlock({
    
        name: name('topface-block'),
        group: top.get('baseGroup'),
        dimensions: ['100%', '100%'],
        start: ['center', 'center'],
        handle: ['center', 'center'],
        fillStyle: name('red-gradient'),
    
    }).clone({
    
        name: name('leftface-block'),
        group: left.get('baseGroup'),
        fillStyle: name('green-gradient'),
    
    }).clone({
    
        name: name('bottomface-block'),
        group: bottom.get('baseGroup'),
        fillStyle: name('yellow-gradient'),
    
    }).clone({
    
        name: name('rightface-block'),
        group: right.get('baseGroup'),
        fillStyle: name('magenta-gradient'),
    
    }).clone({
    
        name: name('frontface-block'),
        group: front.get('baseGroup'),
        fillStyle: name('cyan-gradient'),
    
    }).clone({
    
        name: name('backface-block'),
        group: back.get('baseGroup'),
        fillStyle: name('blue-gradient'),
    });
  • §

    Display a translucent dot on each canvas, pivoted to the mouse

    scrawl.makeWheel({
    
        name: name('topface-dot'),
        group: top.get('baseGroup'),
        radius: '20%',
        handle: ['center', 'center'],
        lockTo: 'mouse',
        fillStyle: 'rgba(127 127 127 / 0.4)',
        strokeStyle: 'rgba(127 127 127 / 0.8)',
        method: 'fillThenDraw',
    
    }).clone({
    
        name: name('leftface-dot'),
        group: left.get('baseGroup'),
    
    }).clone({
    
        name: name('bottomface-dot'),
        group: bottom.get('baseGroup'),
    
    }).clone({
    
        name: name('rightface-dot'),
        group: right.get('baseGroup'),
    
    }).clone({
    
        name: name('frontface-dot'),
        group: front.get('baseGroup'),
    
    }).clone({
    
        name: name('backface-dot'),
        group: back.get('baseGroup'),
    });
  • §

    Add a label to each canvas using a Label entity

    scrawl.makeLabel({
    
        name: name('topface-label'),
        group: top.get('baseGroup'),
        start: ['center', 'center'],
        handle: ['center', 'center'],
        text: 'TOP',
        accessibleText: '§ canvas element',
        fontString: 'bold 3rem sans-serif',
        fillStyle: 'yellow',
        lineWidth: 2,
        method: 'fillThenDraw',
    
      }).clone({
    
        name: name('bottomface-label'),
        group: bottom.get('baseGroup'),
        text: 'BOTTOM',
    
      }).clone({
    
        name: name('leftface-label'),
        group: left.get('baseGroup'),
        text: 'LEFT',
    
      }).clone({
    
        name: name('rightface-label'),
        group: right.get('baseGroup'),
        text: 'RIGHT',
    
      }).clone({
    
        name: name('frontface-label'),
        group: front.get('baseGroup'),
        text: 'FRONT',
    
      }).clone({
    
        name: name('backface-label'),
        group: back.get('baseGroup'),
        text: 'BACK',
      });
  • §

    Scene animation

    const stackCheck = (function () {
    
        let stackActive = false;
        const here = stack.here;
    
        return function () {
    
            if (here.active !== stackActive) {
    
                stackActive = here.active;
    
                pin.set({
                    lockTo: (stackActive) ? 'mouse' : 'start',
                });
            }
        }
    })();
  • §

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

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

    Create the Display cycle animation

    scrawl.makeRender({
    
        name: name('animation'),
        target: stack,
        commence: stackCheck,
        afterShow: report,
    });
    
    scrawl.makeRender({
    
        name: name('canvas-animation'),
        target: [top, bottom, left, right, front, back],
    });
  • §

    Development and testing

    console.log(scrawl.library);