• Jump To … +
    ./source/core/animationloop.js ./source/core/component.js ./source/core/document.js ./source/core/events.js ./source/core/init.js ./source/core/library.js ./source/core/userInteraction.js ./source/core/utilities.js ./source/factory/action.js ./source/factory/anchor.js ./source/factory/animation.js ./source/factory/bezier.js ./source/factory/block.js ./source/factory/canvas.js ./source/factory/cell.js ./source/factory/cog.js ./source/factory/color.js ./source/factory/coordinate.js ./source/factory/element.js ./source/factory/emitter.js ./source/factory/filter.js ./source/factory/fontAttributes.js ./source/factory/gradient.js ./source/factory/grid.js ./source/factory/group.js ./source/factory/imageAsset.js ./source/factory/line.js ./source/factory/loom.js ./source/factory/mesh.js ./source/factory/net.js ./source/factory/noise.js ./source/factory/oval.js ./source/factory/palette.js ./source/factory/particle.js ./source/factory/particleForce.js ./source/factory/particleHistory.js ./source/factory/particleSpring.js ./source/factory/particleWorld.js ./source/factory/pattern.js ./source/factory/phrase.js ./source/factory/picture.js ./source/factory/polygon.js ./source/factory/polyline.js ./source/factory/quadratic.js ./source/factory/quaternion.js ./source/factory/radialGradient.js ./source/factory/rectangle.js ./source/factory/renderAnimation.js ./source/factory/shape.js ./source/factory/spiral.js ./source/factory/spriteAsset.js ./source/factory/stack.js ./source/factory/star.js ./source/factory/state.js ./source/factory/tetragon.js ./source/factory/ticker.js ./source/factory/tracer.js ./source/factory/tween.js ./source/factory/unstackedElement.js ./source/factory/vector.js ./source/factory/videoAsset.js ./source/factory/wheel.js ./source/mixin/anchor.js ./source/mixin/asset.js ./source/mixin/assetConsumer.js ./source/mixin/base.js ./source/mixin/cascade.js ./source/mixin/delta.js ./source/mixin/displayShape.js ./source/mixin/dom.js ./source/mixin/entity.js ./source/mixin/filter.js ./source/mixin/mimic.js ./source/mixin/path.js ./source/mixin/pattern.js ./source/mixin/pivot.js ./source/mixin/position.js ./source/mixin/shapeBasic.js ./source/mixin/shapeCurve.js ./source/mixin/shapePathCalculation.js ./source/mixin/styles.js ./source/mixin/tween.js ./source/worker/filter-string.js ./source/worker/filter.js
  • ¶

    Force factory

    The Scrawl-canvas particle physics engine is a simple system designed to allow developers a way to add particle-based effects to their canvas animation scenes. The physics engine is built on top of the following components:

    • Particle objects, which represent a 3-dimensional coordinate - based on a Scrawl-canvas Vector object - and include a history of recent positions which we can use to determine how to display that particle on screen.
    • History arrays which can be pooled (reused) to cut down on Array creation and distruction during the animation.
    • Force objects which define the general and occasional forces to be applied to each particle in the system as the animation progresses - a gravity force object is pre-defined by Scrawl-canvas.
    • Spring objects used to define a constraint (connection) between two particles in a system.
    • World objects where we can store attributes and values used by various objects; these attributes can be set up so that they will be inherited by clones of the World object. We can also influence the speed of the physics animation here.

    We do not have to handle particle generation and manipulation ourselves. Instead, Scrawl-canvas gives us three dedicated entitys which we use to add particle animation effects to the canvas scene. These entitys are:

    • Tracer - this entity generates a single non-recycled (in other words: long lasting) particle with a history, which we can use to display trace effects in the animation.
    • Emitter - an entity which generates a stream of short-lived, recycled particles, each with its own history. Emitters are highly versatile entitys which can generate a wide range of effects.
    • Net - a (generally) larger entity which uses both forces and springs to manage the animation of its non-recycled particles. Note that other artefacts can use Net particles as a reference for their own positioning.

    Particle physics

    The Scrawl-canvas particle physics engine system is based on a fairly classical understanding of particle kinetics (applying forces and constraints to a small, spherical object in 3D space) and kinematics (the movement of the small object in response to the forces and constraints applied to it).

    A Scrawl-canvas Force object is, essentially, a wrapper around an action function which calculates a force operating on a particle. The force object must have a unique name. Also …

    The action function must accept three arguments, in the following order:

    • a Particle object
    • a World object
    • a Cell object

    The function must add the result of its calculation to the Particle object’s load Vector.

    … See the gravity force, below, for an example of how to construct a Force object.

    The Force factory uses the Base mixin, thus Force objects can be cloned and killed like other Scrawl-canvas objects. Force objects are stored in the scrawl.library.force section of the Scrawl-canvas library object.

  • ¶

    Demos:

    • particles-001 - Emitter entity, and Particle World, basic functionality
    • particles-007 - Particle Force objects: generation and functionality
    • particles-008 - Net entity: generation and basic functionality, including Spring objects
    • particles-009 - Net particles: drag-and-drop functionality
    • particles-012 - Use Net entity particles as reference coordinates for other artefacts
  • ¶

    Imports

    import { constructors } from '../core/library.js';
    import { mergeOver, pushUnique, λnull, isa_fn } from '../core/utilities.js';
    
    import { requestVector, releaseVector } from './vector.js';
    
    import baseMix from '../mixin/base.js';
  • ¶

    Force constructor

    const Force = function (items = {}) {
    
        this.makeName(items.name);
        this.register();
    
        this.set(this.defs);
    
        this.set(items);
    
        if (!this.action) this.action = λnull;
    
        return this;
    };
  • ¶

    Force prototype

    let P = Force.prototype = Object.create(Object.prototype);
    P.type = 'Force';
    P.lib = 'force';
    P.isArtefact = false;
    P.isAsset = false;
  • ¶

    Mixins

    P = baseMix(P);
  • ¶

    Force attributes

    • Attributes defined in the base mixin: name.
    let defaultAttributes = {
    
        action: null,
    };
    P.defs = mergeOver(P.defs, defaultAttributes);
  • ¶

    Packet management

    P.packetFunctions = pushUnique(P.packetFunctions, ['action']);
  • ¶

    Clone management

    No additional clone functionality required

  • ¶

    Kill management

    P.kill = function () {
    
        this.deregister();
    
        return true;
    };
  • ¶

    Get, Set, deltaSet

    let S = P.setters;
    
    S.action = function (item) {
    
        if (isa_fn(item)) this.action = item;
        else this.action = λnull;
    }
  • ¶

    Factory

    let myRepellorBall = scrawl.makeWheel({
    
        name: 'big-ball',
        radius: 30,
    });
    
    scrawl.makeForce({
    
        name: 'example-repellor',
        action: (particle, world, host) => {
    
            let {load, position} = particle;
    
            let ballPosition = myRepellorBall.get('position');
    
            let tempVector = scrawl.requestVector(ballPosition).vectorSubtract(position);
    
            let magnitude = tempVector.getMagnitude();
    
            if (magnitude && magnitude < myRepellorBall.get('radius')) {
    
                tempVector.scalarMultiply(1 / (magnitude / 1000));
                load.vectorSubtract(tempVector)
            }
            scrawl.releaseVector(tempVector);
        },
    });
    const makeForce = function (items) {
        return new Force(items);
    };
    
    constructors.Force = Force;
    
    
    makeForce({
    
        name: 'gravity',
        action: (particle, world, host) => {
    
            let {mass, load} = particle;
    
            let c = requestVector();
    
            c.setFromVector(world.gravity).scalarMultiply(mass);
            load.vectorAdd(c);
    
            releaseVector(c);
        },
    });
  • ¶

    Exports

    export {
        makeForce,
    };