All files / src SSVGDirect.js

89.18% Statements 33/37
80% Branches 16/20
84.61% Functions 11/13
90.32% Lines 28/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                            9x             9x 9x 9x 5x   4x 2x     2x               51x   51x 51x 51x     51x   51x         51x 41x   10x             161x       818x   51x 20x   31x 11x     20x                 827x 827x                 9x   9x    
// @ts-check
 
import { scaleLinear } from 'd3-scale';
import { AttributeType, CalcMode } from './SSVGRelationElement';
import SSVGRelation from './SSVGRelation';
import { TransitionType } from './SSVGTransition';
 
/**
 * @typedef {import('./SSVGState').default} SSVGState
 * @typedef {import('./SSVGProperty').default} SSVGProperty
 */
 
export default class SSVGDirect extends SSVGRelation {
  init() {
    this.animName = 'ssvg-direct-' + this.id;
  }
 
  /**
   * @param {SSVGProperty} prop
   */
  setInitial(prop) {
    this.selection.interrupt(this.animName);
    const value = this.direct(prop.value);
    if (!this.attributeName) {
      this.selection.text(value);
    }
    else if (this.attributeType === AttributeType.CSS) {
      this.selection.style(this.attributeName, value);
    }
    else {
      this.selection.attr(this.attributeName, value);
    }
  }
 
  /**
   * @param {SSVGProperty} prop
   */
  update(prop) {
    this.selection.interrupt(this.animName);
 
    const to = prop.value;
    var t = this.selection.transition(this.animName);
    Iif (this.transition.delay) {
      t = t.delay(this.transition.delay);
    }
    t = t.ease(this.transition.timingFunction);
 
    t = t.duration(this.transition.duration);
 
    /** @type {(t: number) => any} */
    let interpolator;
    // interpolatable target value
    if (Number.isFinite(to) && Number.isFinite(this._last)) {
      interpolator = scaleLinear([ 0, 1 ], [ this._last, to ]);
    }
    else Iif (this.transition.type === TransitionType.direct) {
      // non-interpolatable direct transitions change value at half animation
      // duration
      interpolator = (/** @type {number} */t) => ((t >= 0.5) ? to : this._last);
    }
    else {
      // scaleThreshold simplification
      interpolator = (/** @type {number} */t) => ((t >= 1) ? to : this._last);
    }
 
    /** @type {(t: number) => any} */
    const factory = (t) => this.direct(interpolator(t));
 
    if (!this.attributeName) {
      t.textTween(() => factory);
    }
    else if (this.attributeType === AttributeType.CSS) {
      t.styleTween(this.attributeName, () => factory);
    }
    else {
      t.attrTween(this.attributeName, () => factory);
    }
  }
 
  /**
   * @brief pre-computed target value
   * @param {ssvg.$Value} value
   */
  direct(value) {
    this._last = value;
    return this._filter.filter(value);
  }
 
  /**
   * @brief unused
   * @param {number} n
   */
  strict(n) { return n; }
 
  _parseValues() { return true; }
 
  _parseCalcMode() { return CalcMode.linear; }
}