• Jump To … +
    ./source/asset-management/image-asset.js ./source/asset-management/noise-asset.js ./source/asset-management/raw-asset.js ./source/asset-management/reaction-diffusion-asset.js ./source/asset-management/sprite-asset.js ./source/asset-management/video-asset.js ./source/core/animation-loop.js ./source/core/display-cycle.js ./source/core/document.js ./source/core/events.js ./source/core/init.js ./source/core/library.js ./source/core/snippets.js ./source/core/user-interaction.js ./source/factory/action.js ./source/factory/anchor.js ./source/factory/animation.js ./source/factory/bezier.js ./source/factory/block.js ./source/factory/button.js ./source/factory/canvas.js ./source/factory/cell.js ./source/factory/cog.js ./source/factory/color.js ./source/factory/conic-gradient.js ./source/factory/crescent.js ./source/factory/element.js ./source/factory/emitter.js ./source/factory/enhanced-label.js ./source/factory/filter.js ./source/factory/gradient.js ./source/factory/grid.js ./source/factory/group.js ./source/factory/label.js ./source/factory/line-spiral.js ./source/factory/line.js ./source/factory/loom.js ./source/factory/mesh.js ./source/factory/net.js ./source/factory/oval.js ./source/factory/particle-force.js ./source/factory/particle-spring.js ./source/factory/particle-world.js ./source/factory/particle.js ./source/factory/pattern.js ./source/factory/picture.js ./source/factory/polygon.js ./source/factory/polyline.js ./source/factory/quadratic.js ./source/factory/radial-gradient.js ./source/factory/rectangle.js ./source/factory/render-animation.js ./source/factory/shape.js ./source/factory/spiral.js ./source/factory/stack.js ./source/factory/star.js ./source/factory/tetragon.js ./source/factory/ticker.js ./source/factory/tracer.js ./source/factory/tween.js ./source/factory/unstacked-element.js ./source/factory/wheel.js ./source/helper/array-pool.js ./source/helper/color-engine.js ./source/helper/document-root-elements.js ./source/helper/filter-engine-bluenoise-data.js ./source/helper/filter-engine.js ./source/helper/random-seed.js ./source/helper/shape-path-calculation.js ./source/helper/shared-vars.js ./source/helper/system-flags.js ./source/helper/utilities.js ./source/helper/workstore.js ./source/mixin/anchor.js ./source/mixin/asset-advanced-functionality.js ./source/mixin/asset-consumer.js ./source/mixin/asset.js ./source/mixin/base.js ./source/mixin/button.js ./source/mixin/cascade.js ./source/mixin/cell-key-functions.js ./source/mixin/delta.js ./source/mixin/display-shape.js ./source/mixin/dom.js ./source/mixin/entity.js ./source/mixin/filter.js ./source/mixin/hidden-dom-elements.js ./source/mixin/mimic.js ./source/mixin/path.js ./source/mixin/pattern.js ./source/mixin/pivot.js ./source/mixin/position.js ./source/mixin/shape-basic.js ./source/mixin/shape-curve.js ./source/mixin/styles.js ./source/mixin/text.js ./source/mixin/tween.js ./source/scrawl.js ./source/untracked-factory/cell-fragment.js ./source/untracked-factory/coordinate.js ./source/untracked-factory/drag-zone.js ./source/untracked-factory/keyboard-zone.js ./source/untracked-factory/observe-update.js ./source/untracked-factory/palette.js ./source/untracked-factory/particle-history.js ./source/untracked-factory/quaternion.js ./source/untracked-factory/state.js ./source/untracked-factory/text-style.js ./source/untracked-factory/vector.js
  • §

    DOM event listeners

    Each scrawl-canvas stack and canvas can have bespoke Scrawl-canvas listeners attached to them, to track user mouse and touch interactions with that element. Scrawl-canvas defines five bespoke listeners:

    • move - track mouse cursor and touch movements across the DOM element
    • down - register a new touch interaction, or user pressing the left mouse button
    • up - register the end of a touch interaction, or user releasing the left mouse button
    • enter - trigger an event when the mouse cursor or touch event enters into the DOM element
    • leave - trigger an event when the mouse cursor or touch event exits from the DOM element

    The functions all takes the following arguments:

    • evt - String name of the event (‘move’, ‘down’, ‘up’, ‘enter’, ‘leave’), or an array of such strings
    • fn - the function to be called when the event listener(s) trigger
    • targ - either the DOM element object, or an array of DOM element objects, or a query selector String; these elements need to be registered in the Scrawl-canvas library beforehend (done automatically for stack and canvas elements)
  • §

    Imports

    import { isa_fn, isa_dom, λnull, Ωempty } from "../helper/utilities.js";
    
    import { releaseArray, requestArray } from '../helper/array-pool.js';
  • §

    Shared constants

    import { _isArray, ADD_EVENT_LISTENER, DOWN, ENTER, FUNCTION, LEAVE, MOUSE_DOWN, MOUSE_ENTER, MOUSE_LEAVE, MOUSE_MOVE, MOUSE_UP, MOVE, POINTER_DOWN, POINTER_ENTER, POINTER_LEAVE, POINTER_MOVE, POINTER_UP, REMOVE_EVENT_LISTENER, TOUCH_END, TOUCH_MOVE, TOUCH_START, UP } from '../helper/shared-vars.js';
  • §

    Local constants

    const TOUCH_ENTER = 'touchenter',
        TOUCH_FOLLOW = 'touchfollow',
        TOUCH_LEAVE = 'touchleave';
  • §

    Functionality

    Exported function (to modules and scrawl object) - scrawl.makeAnimationObserver - function to create and start a DOM IntersectionObserver object.

    The function expects 3 arguments, in the following order:

    • a Scrawl-canvas animation object (required) - either Animation or RenderAnimation
    • A Scrawl-canvas element wrapper object (required) - either Canvas, Stack or Element
    • A Javascript object (optional) containing options to be applied to the observer - root, rootMargin, threshold

    The function returns a function which, when invoked, will disconnect the observer from the DOM.

    export const makeAnimationObserver = function (anim, wrapper, specs = Ωempty) {
    
        if (typeof window.IntersectionObserver === FUNCTION && anim && anim.run) {
    
            const observer = new IntersectionObserver((entries) => {
    
                let i, iz, entry;
    
                for (i = 0, iz = entries.length; i < iz; i++) {
    
                    entry = entries[i];
                    if (entry.isIntersecting && !anim.isRunning()) anim.run();
                    else if (!entry.isIntersecting && anim.isRunning()) anim.halt();
                }
            }, specs);
    
            if (wrapper && wrapper.domElement) {
    
                observer.observe(wrapper.domElement);
            }
    
            return function () {
    
                observer.disconnect();
            }
        }
        return λnull;
    }
  • §

    Exported function (to modules and scrawl object) - scrawl.addListener. Returns a kill function which, when invoked (no arguments required), will remove the event listener(s) from all DOM elements to which they have been attached.

    export const addListener = function (evt, fn, targ) {
    
        if (evt && isa_fn(fn) && targ) {
    
            actionListener(evt, fn, targ, REMOVE_EVENT_LISTENER);
            actionListener(evt, fn, targ, ADD_EVENT_LISTENER);
    
            return function () {
    
                removeListener(evt, fn, targ);
            };
        }
        return λnull;
    };
  • §

    Exported function (to modules and scrawl object) - scrawl.removeListener. The counterpart to ‘addListener’ is removeListener which removes Scrawl-canvas event listeners from DOM elements in a similar way

    export const removeListener = function (evt, fn, targ) {
    
        if (evt && isa_fn(fn) && targ) actionListener(evt, fn, targ, REMOVE_EVENT_LISTENER);
    };
  • §

    Because devices and browsers differ in their approach to user interaction (mouse vs pointer vs touch), the actual functionality for adding and removing the event listeners associated with each approach is handled by dedicated actionXXXListener functions

  • §

    TODO: code up the functionality to manage touch events

    const actionListener = function (evt, fn, targ, action) {
    
        const events = requestArray(),
            targets = requestArray();
    
        if (_isArray(evt)) events.push(...evt);
        else events.push(evt);
    
        if (targ.substring) targets.push(...document.body.querySelectorAll(targ));
        else if (_isArray(targ)) targets.push(...targ);
        else targets.push(targ);
    
        if (navigator.pointerEnabled || navigator.msPointerEnabled) actionPointerListener(events, fn, targets, action);
        else actionMouseListener(events, fn, targets, action);
    
        releaseArray(targets, events);
    };
    
    const actionMouseListener = function (events, fn, targets, action) {
    
        let i, iz, j, jz, e, t;
    
        for (i = 0, iz = events.length; i < iz; i++) {
    
            e = events[i];
    
            for (j = 0, jz = targets.length; j < jz; j++) {
    
                t = targets[j];
    
                if (isa_dom(t) || t.document || t.characterSet) {
    
                    switch (e) {
    
                        case MOVE:
                            t[action](MOUSE_MOVE, fn, false);
                            t[action](TOUCH_MOVE, fn, {passive: false});
                            t[action](TOUCH_FOLLOW, fn, {passive: false});
                            break;
    
                        case UP:
                            t[action](MOUSE_UP, fn, false);
                            t[action](TOUCH_END, fn, {passive: false});
                            break;
    
                        case DOWN:
                            t[action](MOUSE_DOWN, fn, false);
                            t[action](TOUCH_START, fn, {passive: false});
                            break;
    
                        case LEAVE:
                            t[action](MOUSE_LEAVE, fn, false);
                            t[action](TOUCH_LEAVE, fn, {passive: false});
                            break;
    
                        case ENTER:
                            t[action](MOUSE_ENTER, fn, false);
                            t[action](TOUCH_ENTER, fn, {passive: false});
                            break;
                    }
                }
            }
        }
    };
    
    const actionPointerListener = function (events, fn, targets, action) {
    
        let i, iz, j, jz, e, t;
    
        for (i = 0, iz = events.length; i < iz; i++) {
    
            e = events[i];
    
            for (j = 0, jz = targets.length; j < jz; j++) {
    
                t = targets[j];
    
                if (isa_dom(t) || t.document || t.characterSet) {
    
                    switch (e) {
    
                        case MOVE:
                            t[action](POINTER_MOVE, fn, false);
                            break;
    
                        case UP:
                            t[action](POINTER_UP, fn, false);
                            break;
    
                        case DOWN:
                            t[action](POINTER_DOWN, fn, false);
                            break;
    
                        case LEAVE:
                            t[action](POINTER_LEAVE, fn, false);
                            break;
    
                        case ENTER:
                            t[action](POINTER_ENTER, fn, false);
                            break;
                    }
                }
            }
        }
    };
  • §

    Any event listener can be added to a Scrawl-canvas stack or canvas DOM element.

    The scrawl.addNativeListener function makes adding and removing these ‘native’ listeners a little easier: multiple event listeners (which all trigger the same function) can be added to multiple DOM elements (that have been registered in the Scrawl-canvas library) in a single function call.

    The function requires three arguments:

    • evt - String name of the event (‘click’, ‘input’, ‘change’, etc), or an array of such strings
    • fn - the function to be called when the event listener(s) trigger
    • targ - either the DOM element object, or an array of DOM element objects, or a query selector String. Note that window and ``
  • §

    Exported function (to modules and scrawl object). Returns a kill function which, when invoked (no arguments required), will remove the event listener(s) from all DOM elements to which they have been attached.

    export const addNativeListener = function (evt, fn, targ) {
    
        if (evt && isa_fn(fn) && targ) {
    
            actionNativeListener(evt, fn, targ, REMOVE_EVENT_LISTENER);
            actionNativeListener(evt, fn, targ, ADD_EVENT_LISTENER);
    
            return function () {
    
                removeNativeListener(evt, fn, targ);
            };
        }
        return λnull;
    };
  • §

    Exported function (to modules and scrawl object). The counterpart to ‘addNativeListener’ is scrawl.removeNativeListener which removes event listeners from DOM elements in a similar way

    export const removeNativeListener = function (evt, fn, targ) {
    
        if (evt && isa_fn(fn) && targ) actionNativeListener(evt, fn, targ, REMOVE_EVENT_LISTENER);
    };
    
    const actionNativeListener = function (evt, fn, targ, action) {
    
        const events = requestArray(),
            targets = requestArray();
    
        let i, iz, j, jz, e, t;
    
        if (_isArray(evt)) events.push(...evt);
        else events.push(evt);
    
        if (targ.substring) targets.push(...document.body.querySelectorAll(targ));
        else if (_isArray(targ)) targets.push(...targ);
        else targets.push(targ);
    
        for (i = 0, iz = events.length; i < iz; i++) {
    
            e = events[i];
    
            for (j = 0, jz = targets.length; j < jz; j++) {
    
                t = targets[j];
    
                if (isa_dom(t) || t.document || t.characterSet) t[action](e, fn, false);
            }
        }
        releaseArray(targets, events);
    };