• 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-015a.js ./demo/canvas-016.js ./demo/canvas-017.js ./demo/canvas-018.js ./demo/canvas-019.js ./demo/canvas-019a.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/core-001.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/filters-001.js ./demo/filters-002.js ./demo/filters-002a.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-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/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/rapier-001.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-000.js ./demo/temp-001.js ./demo/temp-001a.js ./demo/temp-002.js ./demo/temp-003.js ./demo/temp-004.js ./demo/temp-005.js ./demo/temp-006.js ./demo/temp-007.js ./demo/temp-008.js ./demo/temp-009.js ./demo/temp-010.js ./demo/temp-011.js ./demo/temp-012.js ./demo/temp-013.js ./demo/temp-014.js ./demo/temp-015.js ./demo/temp-016.js ./demo/temp-017.js ./demo/temp-018.js ./demo/temp-018a.js ./demo/temp-019.js ./demo/temp-020.js ./demo/temp-021.js ./demo/temp-022.js ./demo/temp-023.js ./demo/temp-024.js ./demo/temp-025.js ./demo/temp-026.js ./demo/temp-027.js ./demo/temp-028.js ./demo/temp-029.js ./demo/temp-030.js ./demo/temp-031.js ./demo/temp-032.js ./demo/temp-033.js ./demo/temp-034.js ./demo/temp-035.js ./demo/temp-036.js ./demo/temp-037.js ./demo/temp-100.js ./demo/temp-101.js ./demo/temp-102.js ./demo/temp-103.js ./demo/temp-104.js ./demo/temp-200.js ./demo/temp-201.js ./demo/temp-301.js ./demo/temp-inkscapeSvgFilters.js ./demo/temp-lottie.js ./demo/tensorflow-001.js ./demo/tensorflow-002.js ./demo/utilities.js
  • §

    Demo Canvas 015a

    Phrase entity - cache output to improve render speeds

  • §

    Run code

    import {
        createImageFromEntity,
        library as L,
        makeDragZone,
        makePhrase,
        makePicture,
        makeRender,
    } from '../source/scrawl.js'
    
    import { reportSpeed } from './utilities.js';
  • §

    Scene setup

    let canvas = L.artefact.mycanvas,
        entitys = L.entity;
  • §

    Create and clone Phrase entitys

    makePhrase({
        name: 'myphrase_fill',
    
        text: 'Hεljö!',
        font: 'bold 40px Garamond, serif',
    
        startX: '14%',
        startY: '28%',
        handleX: 'center',
        handleY: 'center',
    
        fillStyle: 'green',
        strokeStyle: 'gold',
    
        lineWidth: 2,
        lineJoin: 'round',
        shadowOffsetX: 2,
        shadowOffsetY: 2,
        shadowBlur: 2,
        shadowColor: 'black',
    
        lineHeight: 1,
    
    }).clone({
        name: 'myphrase_draw',
        startX: '38%',
        method: 'draw',
    
    }).clone({
        name: 'myphrase_drawAndFill',
        startX: '84%',
        method: 'drawAndFill',
    
    }).clone({
        name: 'myphrase_fillAndDraw',
        startX: '62%',
        method: 'fillAndDraw',
        sharedState: true
    
    }).clone({
        name: 'myphrase_drawThenFill',
        startX: '14%',
        startY: '67%',
        method: 'drawThenFill'
    
    }).clone({
        name: 'myphrase_fillThenDraw',
        startX: '38%',
        method: 'fillThenDraw',
    
    }).clone({
        name: 'myphrase_clear',
        startX: '62%',
        method: 'clear'
    
    }).clone({
        name: 'myphrase_multiline',
    
        text: 'Lorem ipsum har varit standard ända sedan 1500-talet, när-en-okänd-boksättare-tog att antal bokstäver och blandade dem för att göra ett provexemplar av en bok.',
    
        width: 120,
        justify: 'center',
    
        size: '12px',
        weight: 'normal',
    
        startX: '84%',
        method: 'fill',
    
        shadowOffsetX: 0,
        shadowOffsetY: 0,
        shadowBlur: 0,
    });
  • §

    Change the fill and stroke styles on one of the phrase entitys, and any entity sharing that phrase’s state

    L.artefact.myphrase_fillAndDraw.set({
        fillStyle: 'blue',
        strokeStyle: 'coral'
    });
  • §

    Caching entity output

    A one-off instruction to tell Scrawl-canvas to create image assets from our Phrase entitys the next time it performs a Display cycle

    • By caching entity output in <img> elements, we can then replace the Phrase entitys with Picture entitys that use the cached image as their asset source. As graphic text output is an expensive operation for the canvas element to perform - particularly when we apply a shadow blur to the text - it will often make sense to replace such Phrase entitys with Picture entitys.
    • This approach is less useful for text that updates frequently, or uses dynamic fill/stroke styling
    createImageFromEntity(entitys.myphrase_fill, true);
    createImageFromEntity(entitys.myphrase_draw, true);
    createImageFromEntity(entitys.myphrase_drawAndFill, true);
    createImageFromEntity(entitys.myphrase_fillAndDraw, true);
    createImageFromEntity(entitys.myphrase_drawThenFill, true);
    createImageFromEntity(entitys.myphrase_fillThenDraw, true);
    createImageFromEntity(entitys.myphrase_clear, true);
    createImageFromEntity(entitys.myphrase_multiline, true);
  • §

    User interaction

    Create the drag-and-drop zone

    let current = makeDragZone({
    
        zone: canvas,
        endOn: ['up', 'leave'],
        exposeCurrentArtefact: true,
        preventTouchDefaultWhenDragging: true,
    });
  • §

    Scene animation

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

    const report = reportSpeed('#reportmessage', function () {
        const dragging = current();
        return `Currently dragging: ${(typeof dragging !== 'boolean' && dragging) ? dragging.artefact.name : 'nothing'}`;
    });
  • §

    Create the Display cycle animation

    makeRender({
    
        name: 'demo-animation',
        target: canvas,
        afterShow: report,
  • §

    Caching (continued)

    After the first iteration of the Display cycle, we can create Picture entitys to replace our Phrase entitys

    • As the content and display of the text does not change (only their positions change when users drag-and-drop them), we can treat the creation of the cache images and associated entitys as a one-off job
        afterCreated: () => {
    
            let g = L.group[canvas.base.name];
  • §

    Switch off the Phrase entitys via a set call to their Group (which, in this instance is the canvas.base Cell’s default Group)

            g.setArtefacts({
                visibility: false,
            });
    
            let keys = g.artefacts;
  • §

    Generate Picture entitys, using the existing Phrase entitys for positional and dimensional data

            keys.forEach(name => {
    
                let e = entitys[name];
    
                if (e) {
    
                    makePicture({
    
                        name: `${name}-cached`,
    
                        start: e.get('start'),
                        handle: e.get('handle'),
                        dimensions: e.get('dimensions'),
    
                        asset: `${name}-image`,
                        copyDimensions: ['100%', '100%'],
    
                        strokeStyle: 'red',
                        method: 'fillThenDraw',
                    });
                }
            });
        },
    });
  • §

    Development and testing

    console.log(L);