• 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/component-001.js ./demo/component-002.js ./demo/component-003.js ./demo/component-004.js ./demo/component-005.js ./demo/component-006.js ./demo/component-007.js ./demo/core-001.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-014a.js ./demo/dom-014b.js ./demo/dom-014c.js ./demo/dom-015.js ./demo/dom-016.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-501.js ./demo/filters-502.js ./demo/filters-503.js ./demo/filters-504.js ./demo/filters-505.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/temp-001.js ./demo/temp-inkscapeSvgFilters.js
  • ¶

    Demo Canvas 010

    Use video sources and media streams for Picture entitys

  • ¶

    Run code

    import scrawl from '../source/scrawl.js'
  • ¶

    Scene setup

    let canvas = scrawl.library.artefact.mycanvas;
  • ¶
    Importing video sources
  • ¶

    Get video stream from DOM <video> element

    • When loading video assets from the DOM, note that Scrawl-canvas has to deal with the <video> element operating under normal DOM rules. This means that (in most modern browsers) the video will not fetch anything beyond its metadata until at least 1px height of the video is displayed in the viewport (videos hidden by any CSS rules will not fetch anything until they are made visible).
    • The practical implications of this is that any Picture entitys relying on the video as their asset will not display an image until the DOM video element appears in the user’s viewport.
    • To make sure the Picture entity displays the video’s first frame, we need to explicitly set the DOM element’s preload attribute to auto
    scrawl.importDomVideo('.myvideo');
  • ¶

    Create Picture entity from video entity included in the DOM

    let viddyOne = scrawl.makePicture({
    
        name: 'first-video',
        asset: 'waves',
    
        width: 200,
        height: 200,
    
        startX: 300,
        startY: 200,
        handleX: 100,
        handleY: 100,
    
        copyWidth: 200,
        copyHeight: 200,
        copyStartX: 100,
        copyStartY: 100,
    
        lineWidth: 10,
        strokeStyle: 'lightgreen',
    
        order: 1,
        method: 'drawThenFill',
    
    });
  • ¶

    Import a video from a remote server

    let viddyTwo = scrawl.makePicture({
    
        name: 'second-video',
        videoSource: 'img/Motion - 18249.mp4',
    
        width: '100%',
        height: '100%',
    
        copyWidth: '100%',
        copyHeight: '100%',
    
        order: 0,
        method: 'fill',
    });
  • ¶

    Display a device-based media stream in a Picture entity

    • Note 1: Users will need to explicitly agree to let Scrawl-canvas use the media stream the first time the page loads (the browser should handle this agreement procedure itself)
    • Note 2: importMediaStream returns a Promise!
    let viddyThree;
    
    scrawl.importMediaStream({
        audio: false,
    })
    .then(myface => {
    
        viddyThree = scrawl.makePicture({
    
            name: 'mediastream-video',
            asset: myface.name,
    
            startX: '20%',
            startY: '20%',
            handleX: 'center',
            handleY: 'center',
    
            width: '40%',
            height: '40%',
    
            copyWidth: '100%',
            copyHeight: '100%',
    
            lineWidth: 6,
            strokeStyle: 'pink',
    
            order: 0,
            method: 'drawThenFill',
        });
  • ¶

    Adding some controls to manipulate the media stream’s display

    • For this demo, we’ll use the existing controls setup for manipulating the DOM video
        scrawl.observeAndUpdate({
    
            event: ['input', 'change'],
            origin: '.controlItem',
    
            target: viddyThree,
    
            useNativeListener: true,
            preventDefault: true,
    
            updates: {
    
                copy_start_xPercent: ['copyStartX', '%'],
                copy_start_xAbsolute: ['copyStartX', 'round'],
    
                copy_start_yPercent: ['copyStartY', '%'],
                copy_start_yAbsolute: ['copyStartY', 'round'],
    
                copy_dims_widthPercent: ['copyWidth', '%'],
                copy_dims_widthAbsolute: ['copyWidth', 'round'],
    
                copy_dims_heightPercent: ['copyHeight', '%'],
                copy_dims_heightAbsolute: ['copyHeight', 'round'],
    
                upend: ['flipUpend', 'boolean'],
                reverse: ['flipReverse', 'boolean'],
            },
        });
    })
    .catch(err => console.log(err.message));
  • ¶

    Scene animation

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

    let report = function () {
    
        let testTicker = Date.now(),
            testTime, testNow,
            testMessage = document.querySelector('#reportmessage');
    
        return function () {
    
            testNow = Date.now();
            testTime = testNow - testTicker;
            testTicker = testNow;
    
            testMessage.textContent = `Screen refresh: ${Math.ceil(testTime)}ms; fps: ${Math.floor(1000 / testTime)}`;
        };
    }();
  • ¶

    Create the Display cycle animation

    scrawl.makeRender({
    
        name: 'demo-animation',
        target: canvas,
        afterShow: report,
    });
  • ¶

    User interaction

    Setup form observer functionality

    scrawl.observeAndUpdate({
    
        event: ['input', 'change'],
        origin: '.controlItem',
    
        target: viddyOne,
    
        useNativeListener: true,
        preventDefault: true,
    
        updates: {
    
            copy_start_xPercent: ['copyStartX', '%'],
            copy_start_xAbsolute: ['copyStartX', 'round'],
    
            copy_start_yPercent: ['copyStartY', '%'],
            copy_start_yAbsolute: ['copyStartY', 'round'],
    
            copy_dims_widthPercent: ['copyWidth', '%'],
            copy_dims_widthAbsolute: ['copyWidth', 'round'],
    
            copy_dims_heightPercent: ['copyHeight', '%'],
            copy_dims_heightAbsolute: ['copyHeight', 'round'],
    
            paste_dims_widthPercent: ['width', '%'],
            paste_dims_widthAbsolute: ['width', 'round'],
    
            paste_dims_heightPercent: ['height', '%'],
            paste_dims_heightAbsolute: ['height', 'round'],
    
            paste_start_xPercent: ['startX', '%'],
            paste_start_xAbsolute: ['startX', 'round'],
            paste_start_xString: ['startX', 'raw'],
    
            paste_start_yPercent: ['startY', '%'],
            paste_start_yAbsolute: ['startY', 'round'],
            paste_start_yString: ['startY', 'raw'],
    
            paste_handle_xPercent: ['handleX', '%'],
            paste_handle_xAbsolute: ['handleX', 'round'],
            paste_handle_xString: ['handleX', 'raw'],
    
            paste_handle_yPercent: ['handleY', '%'],
            paste_handle_yAbsolute: ['handleY', 'round'],
            paste_handle_yString: ['handleY', 'raw'],
    
            roll: ['roll', 'float'],
            scale: ['scale', 'float'],
    
            upend: ['flipUpend', 'boolean'],
            reverse: ['flipReverse', 'boolean'],
        },
    });
  • ¶

    Add an additional click event listener

    • Because many browsers/devices will not allow video to be played until a user interacts with it in some way
    scrawl.addListener('up', function () {
    
        viddyOne.set({
            video_muted: true,
            video_loop: true,
        }).videoPlay();
    
        viddyTwo.set({
            video_muted: true,
            video_loop: true,
        }).videoPlay();
    
    }, canvas.domElement);
  • ¶

    Setup form

    document.querySelector('#copy_start_xPercent').value = 25;
    document.querySelector('#copy_start_yPercent').value = 25;
    document.querySelector('#copy_dims_widthPercent').value = 50;
    document.querySelector('#copy_dims_widthAbsolute').value = 200;
    document.querySelector('#copy_start_xAbsolute').value = 100;
    document.querySelector('#copy_start_yAbsolute').value = 100;
    document.querySelector('#copy_dims_heightPercent').value = 50;
    document.querySelector('#copy_dims_heightAbsolute').value = 200;
    document.querySelector('#paste_dims_widthPercent').value = 33;
    document.querySelector('#paste_dims_widthAbsolute').value = 200;
    document.querySelector('#paste_dims_heightPercent').value = 50;
    document.querySelector('#paste_dims_heightAbsolute').value = 200;
    document.querySelector('#paste_start_xPercent').value = 50;
    document.querySelector('#paste_start_yPercent').value = 50;
    document.querySelector('#paste_handle_xPercent').value = 50;
    document.querySelector('#paste_handle_yPercent').value = 50;
    document.querySelector('#paste_start_xAbsolute').value = 300;
    document.querySelector('#paste_start_yAbsolute').value = 200;
    document.querySelector('#paste_handle_xAbsolute').value = 100;
    document.querySelector('#paste_handle_yAbsolute').value = 100;
    document.querySelector('#paste_start_xString').options.selectedIndex = 1;
    document.querySelector('#paste_start_yString').options.selectedIndex = 1;
    document.querySelector('#paste_handle_xString').options.selectedIndex = 1;
    document.querySelector('#paste_handle_yString').options.selectedIndex = 1;
    document.querySelector('#roll').value = 0;
    document.querySelector('#scale').value = 1;
    document.querySelector('#upend').options.selectedIndex = 0;
    document.querySelector('#reverse').options.selectedIndex = 0;