• 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
  • §

    Delta mixin

    This mixin defines additional attributes and functions for an artefact that uses delta functionality

  • §

    Imports

    import { mergeDiscard, mergeOver, Ωempty } from '../helper/utilities.js';
  • §

    Shared constants

    import { _isArray, _keys, MULTIPLY, PC, ZERO_STR } from '../helper/shared-vars.js'
  • §

    Local constants

    const ADD = 'add',
        LONGCHECK = ['startX', 'startY', 'handleX', 'handleY', 'offsetX', 'offsetY', 'width', 'height'],
        LOOP = 'loop',
        NEWNUMBER = 'newNumber',
        NEWSTRING = 'newString',
        REMOVE = 'remove',
        REVERSE = 'reverse',
        SEPARATOR = ':',
        SHORTCHECK = ['startY', 'handleY', 'offsetY', 'height'],
        UPDATE = 'update';
  • §

    Export function

    export default function (P = Ωempty) {
  • §

    Shared attributes

        const defaultAttributes = {
  • §

    delta - a Javascript object containing {key:value, key:value, etc} attributes.

    • As part of the Display cycle, delta values get added to artefact attribute values - this is a very simple form of animation.
    • deltaConstraints - Object mirroring the delta object which we use to set bounds on the delta values, and instructions on what to do when those bounds are crossed.
    • noDeltaUpdates - Boolean flag to switch off the automatic application of delta attribute values as part of each iteration of the Display cycle.
    • checkDeltaConstraints - Boolean flag to switch ON automatic constraint checks.
    • Delta updates can be invoked independently from the Display cycle by invoking artefact.updateByDelta, artefact.reverseByDelta.
    • In addition to using artefact.set, we can also update the delta object values using artefact.setDeltaValues.
    // This Block artefact will animate itself across the <canvas> element
    // - it will move to the right and upwards until the `delta` values are updated
    // - animation will stop when the `noDeltaUpdates` flag is set
    let myBlock = scrawl.makeBlock({
        start: ['left', 500],
        delta: {
            startX: 0.5,
            startY: '-0.3',
        },
        noDeltaUpdates: false,
    });
    

    Note that the delta and deltaConstraints objects are set up in the mixin/position.js module, not here

            delta: null,
            noDeltaUpdates: false,
            deltaConstraints: null,
            checkDeltaConstraints: false,
  • §

    We do not want to perform any delta checks on any uninitalized attributes - in other words: no checks on the first iteration of the Display cycle

            performDeltaChecks: false,
    
        };
        P.defs = mergeOver(P.defs, defaultAttributes);
  • §

    Packet management

    No additional packet management functionality defined here

  • §

    Clone management

    No additional clone functionality defined here

  • §

    Kill management

    No additional kill functionality defined here

  • §

    Get, Set, deltaSet

        const S = P.setters;
  • §

    delta

        S.delta = function (items = Ωempty) {
    
            if (items) this.delta = mergeDiscard(this.delta, items);
        };
    
    
        S.deltaConstraints = function (items = Ωempty) {
    
            if (items) this.deltaConstraints = mergeDiscard(this.deltaConstraints, items);
        };
  • §

    Prototype functions

  • §

    updateByDelta - this function gets called as part of every display cycle iteration, meaning that if an attribute is set to a non-zero value in the delta attribute object then those delta animations will start playing immediately.

        P.updateByDelta = function () {
    
            this.setDelta(this.delta);
    
            if (this.checkDeltaConstraints) this.performDeltaConstraintsChecks();
    
            return this;
        };
  • §

    reverseByDelta - The opposite action to ‘updateByDelta’; values in the delta attribute object will be subtracted from the current value for that Scrawl-canvas object.

        P.reverseByDelta = function () {
    
            const temp = {},
                delta = this.delta,
                deltaKeys = _keys(delta),
                deltaLen = deltaKeys.length;
    
            let i, key, val;
    
            for (i = 0; i < deltaLen; i++) {
    
                key = deltaKeys[i];
                val = delta[key];
    
                if (val.substring) val = -(parseFloat(val)) + PC;
                else val = -val;
    
                temp[key] = val;
            }
            this.setDelta(temp);
    
            if (this.checkDeltaConstraints) this.performDeltaConstraintsChecks();
    
            return this;
        };
    
        P.performDeltaConstraintsChecks = function () {
    
            const {delta, deltaConstraints} = this;
    
            if (this.performDeltaChecks) {
    
                const keys = _keys(deltaConstraints),
                    keysLen = keys.length;
    
                let key, keyIndex, item, min, max, action, act, loopAct, arr, valIndex, val, i, fMin, fMax, fVal;
    
                for (i = 0; i < keysLen; i++) {
    
                    key = keys[i];
                    item = deltaConstraints[key];
    
                    if (_isArray(item) && item.length === 3) {
    
                        [min, max, action] = deltaConstraints[key];
    
                        if (min.substring) {
    
                            keyIndex = LONGCHECK.indexOf(key);
                            arr = false;
                            valIndex = 0;
    
                            if (keyIndex >= 0) {
    
                                if (keyIndex < 2) arr = this.start;
                                else if (keyIndex < 4) arr = this.handle;
                                else if (keyIndex < 6) arr = this.offset;
                                else if (keyIndex < 8) arr = this.dimensions;
    
                                if (SHORTCHECK.includes(key)) valIndex = 1;
    
                                val = arr[valIndex];
                            }
                            else val = this.get(key);
    
                            fMin = parseFloat(min);
                            fMax = parseFloat(max);
                            fVal = parseFloat(val);
                            act = ZERO_STR;
    
                            if (fVal < fMin) {
    
                                act = action;
                                loopAct = 0;
                            }
                            else if (fVal > fMax) {
    
                                act = action;
                                loopAct = 1;
                            }
    
                            if (act) {
    
                                switch (act) {
    
                                    case REVERSE :
    
                                        delta[key] = -parseFloat(delta[key]) + PC;
    
                                        this.set({
                                            [key]: fVal + parseFloat(delta[key]) + PC,
                                        });
                                        break;
    
                                    case LOOP :
    
                                        if (loopAct) {
    
                                            this.set({
                                                [key]: fVal - (fMax - fMin) + PC,
                                            });
                                        }
                                        else {
    
                                            this.set({
                                                [key]: fVal + (fMax - fMin) + PC,
                                            });
                                        }
                                        break;
                                }
                            }
                        }
                        else {
    
                            val = this.get(key);
    
                            act = ZERO_STR;
    
                            if (val < min) {
    
                                act = action;
                                loopAct = 0;
                            }
                            else if (val > max) {
    
                                act = action;
                                loopAct = 1;
                            }
    
                            if (act) {
    
                                switch (act) {
    
                                    case REVERSE :
    
                                        delta[key] = -delta[key];
    
                                        this.set({
                                            [key]: val + delta[key],
                                        });
                                        break;
    
                                    case LOOP :
    
                                        if (loopAct) {
    
                                            this.set({
                                                [key]: val - (max - min),
                                            });
                                        }
                                        else {
    
                                            this.set({
                                                [key]: val + (max - min),
                                            });
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
            }
            else this.performDeltaChecks = true;
        };
  • §

    setDeltaValues - warning: EXPERIMENTAL and not currently tested! Update the artefact’s delta object in a more intelligent way. The function accepts an object argument containing a set of instructions which will be interpreted and applied to the delat object.

    // Original delta object:
    artefact.delta: {
        width: 50,
        height: '20%',
        scale: 2,
    }
    
    // Function argument object to be applied to the delta object:
    {
        width: 'add:20',
        height: 'multiply:0.8',
        scale: 'remove',
        roll: 'newNumber:45',
    }
    
    // Result of applying the argument to the delta object:
    artefact.delta: {
        width: 70,
        height: '16%',
        roll: 45,
    }
    
        P.setDeltaValues = function (items = Ωempty) {
    
            const delta = this.delta,
                keys = _keys(items),
                keysLen = keys.length;
    
            let i, key, item, action, val, old
    
            for (i = 0; i < keysLen; i++) {
    
                key = keys[i];
                item = items[key];
                old = delta[key];
    
                if (!item.includes(SEPARATOR)) {
                    action = item;
                    val = false;
                }
                else {
                    [action, val] = item.split(SEPARATOR);
                }
    
                switch (action) {
    
                    case NEWSTRING :
                        if (val != null) delta[key] = val;
                        break;
    
                    case NEWNUMBER :
                        if (val != null) delta[key] = parseFloat(val);
                        break;
    
                    case REMOVE :
                        delete delta[key];
                        break;
    
                    case UPDATE :
                        if (val != null) delta[key] = (old.substring) ? val : parseFloat(val);
                        break;
    
                    case REVERSE :
                        if (old.substring) val = -(parseFloat(old)) + PC;
                        else val = -old;
                        delta[key] = val;
                        break;
    
                    case ADD :
                        if (old.substring) val = (parseFloat(old) + parseFloat(val)) + PC;
                        else val += old;
                        delta[key] = val;
                        break;
    
                    case MULTIPLY :
                        if (old.substring) val = (parseFloat(old) * parseFloat(val)) + PC;
                        else val *= old;
                        delta[key] = val;
                        break;
                }
            }
            return this;
        };
    }