- Jump To … +
  ./source/core/animation-loop.js ./source/core/display-cycle.js ./source/core/document-root-elements.js ./source/core/document.js ./source/core/events.js ./source/core/init.js ./source/core/library.js ./source/core/random-seed.js ./source/core/shared-vars.js ./source/core/snippets.js ./source/core/system-flags.js ./source/core/user-interaction.js ./source/core/utilities.js ./source/factory/action.js ./source/factory/anchor.js ./source/factory/animation.js ./source/factory/array-pool.js ./source/factory/bezier.js ./source/factory/block.js ./source/factory/canvas.js ./source/factory/cell-fragment.js ./source/factory/cell.js ./source/factory/cog.js ./source/factory/color.js ./source/factory/conic-gradient.js ./source/factory/coordinate.js ./source/factory/crescent.js ./source/factory/drag-zone.js ./source/factory/element.js ./source/factory/emitter.js ./source/factory/filter-engine-bluenoise-data.js ./source/factory/filter-engine.js ./source/factory/filter.js ./source/factory/font-attributes.js ./source/factory/gradient.js ./source/factory/grid.js ./source/factory/group.js ./source/factory/image-asset.js ./source/factory/keyboard-zone.js ./source/factory/line-spiral.js ./source/factory/line.js ./source/factory/loom.js ./source/factory/mesh.js ./source/factory/net.js ./source/factory/noise-asset.js ./source/factory/observe-update.js ./source/factory/oval.js ./source/factory/palette.js ./source/factory/particle-force.js ./source/factory/particle-history.js ./source/factory/particle-spring.js ./source/factory/particle-world.js ./source/factory/particle.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/radial-gradient.js ./source/factory/raw-asset.js ./source/factory/reaction-diffusion-asset.js ./source/factory/rectangle.js ./source/factory/render-animation.js ./source/factory/shape.js ./source/factory/spiral.js ./source/factory/sprite-asset.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/unstacked-element.js ./source/factory/vector.js ./source/factory/video-asset.js ./source/factory/wheel.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/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/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/shape-path-calculation.js ./source/mixin/styles.js ./source/mixin/tween.js

- §

  # Delta mixin

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

- §

  #### Imports

      import { mergeDiscard, mergeOver, Ωempty } from '../core/utilities.js';

      import { _isArray, _keys, ADD, LONGCHECK, LOOP, MULTIPLY, NEWNUMBER, NEWSTRING, PC, REMOVE, REVERSE, SEPARATOR, SHORTCHECK, UPDATE, ZERO_STR } from '../core/shared-vars.js'

- §

  #### 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);
          mergeOver(P, 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` 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;
          };
      }