All files / src AxisManager.ts

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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152        10x 10x                           10x   298x 298x 298x 592x 592x       10x 339x 630x     2691x 2691x 714x 1166x 1162x   1166x     1977x       6662x 6349x 11524x     6349x   10851x     6349x           10x 11075x 18643x 18642x         10x       4201x   4619x     10x       91x   166x     10x       26119x   26119x 43677x       10x 379x   658x       10x 13x     10x 1x 2x     2x         1x             299x 299x 594x                   594x 1188x 1188x   1188x 212x         10x  
/*
 * Copyright (c) 2015 NAVER Corp.
 * egjs projects are licensed under the MIT license
 */
import { isOutside, getCirculatedPos } from "./Coordinate";
import { map, filter, every } from "./utils";
import { ObjectInterface } from "./types";
 
export interface Axis {
  [key: string]: number;
}
 
export interface AxisOption {
  range?: number[];
  bounce?: number | number[];
  circular?: boolean | boolean[];
  startPos?: number;
}
 
export class AxisManager {
  private _pos: Axis;
  public constructor(private _axis: ObjectInterface<AxisOption>) {
    this._complementOptions();
    this._pos = Object.keys(this._axis).reduce((pos, v) => {
      pos[v] = this._axis[v].startPos;
      return pos;
    }, {});
  }
 
  public getDelta(depaPos: Axis, destPos: Axis): Axis {
    const fullDepaPos = this.get(depaPos);
    return map(this.get(destPos), (v, k) => v - fullDepaPos[k]);
  }
 
  public get(axes?: string[] | Axis): Axis {
    if (axes && Array.isArray(axes)) {
      return axes.reduce((acc, v) => {
        if (v && v in this._pos) {
          acc[v] = this._pos[v];
        }
        return acc;
      }, {});
    } else {
      return { ...this._pos, ...((axes || {}) as Axis) };
    }
  }
 
  public moveTo(pos: Axis, depaPos: Axis = this._pos): { [key: string]: Axis } {
    const delta = map(this._pos, (v, key) => {
      return key in pos && key in depaPos ? pos[key] - depaPos[key] : 0;
    });
 
    this.set(
      this.map(pos, (v, opt) =>
        opt ? getCirculatedPos(v, opt.range, opt.circular as boolean[]) : 0
      )
    );
    return {
      pos: { ...this._pos },
      delta,
    };
  }
 
  public set(pos: Axis) {
    for (const k in pos) {
      if (k && k in this._pos) {
        this._pos[k] = pos[k];
      }
    }
  }
 
  public every(
    pos: Axis,
    callback: (value: number, options: AxisOption, key: string) => boolean
  ): boolean {
    const axisOptions = this._axis;
 
    return every(pos, (value, key) => callback(value, axisOptions[key], key));
  }
 
  public filter(
    pos: Axis,
    callback: (value: number, options: AxisOption, key: string) => boolean
  ): Axis {
    const axisOptions = this._axis;
 
    return filter(pos, (value, key) => callback(value, axisOptions[key], key));
  }
 
  public map<U>(
    pos: Axis,
    callback: (value: number, options: AxisOption, key: string) => U
  ) {
    const axisOptions = this._axis;
 
    return map<number, U>(pos, (value, key) =>
      callback(value, axisOptions[key], key)
    );
  }
 
  public isOutside(axes?: string[]) {
    return !this.every(
      axes ? this.get(axes) : this._pos,
      (v, opt) => !isOutside(v, opt.range)
    );
  }
 
  public getAxisOptions(key: string) {
    return this._axis[key];
  }
 
  public setAxis(axis: ObjectInterface<AxisOption>) {
    Object.keys(axis).forEach((key) => {
      Iif (!this._axis[key]) {
        throw new Error(`Axis ${key} does not exist in Axes instance`);
      }
      this._axis[key] = {
        ...this._axis[key],
        ...axis[key],
      };
    });
    this._complementOptions();
  }
 
  /**
   * set up 'css' expression
   * @private
   */
  private _complementOptions() {
    Object.keys(this._axis).forEach((axis) => {
      this._axis[axis] = {
        ...{
          range: [0, 100],
          startPos: this._axis[axis].range[0],
          bounce: [0, 0],
          circular: [false, false],
        },
        ...this._axis[axis],
      };
 
      ["bounce", "circular"].forEach((v) => {
        const axisOption = this._axis;
        const key = axisOption[axis][v];
 
        if (/string|number|boolean/.test(typeof key)) {
          axisOption[axis][v] = [key, key];
        }
      });
    });
  }
}