⌈⌋ ⎇ branch:  Bitrhythm


Artifact Content

Artifact ec17133aa32ad2d508ddd19fbe8a56eee48e3b1d231e1adc25b7034e467ce668:



'use strict';

let svg = require('../util/svg');
let Interface = require('../core/interface');
let Step = require('../models/step');
import * as Interaction from '../util/interaction';

/**
* Position
*
* @description Two-dimensional touch slider.
*
* @demo <span nexus-ui="position"></span>
*
* @example
* var position = new Nexus.Position('#target')
*
* @example
* var position = new Nexus.Position('#target',{
*   'size': [200,200],
*   'mode': 'absolute',  // "absolute" or "relative"
*   'x': 0.5,  // initial x value
*   'minX': 0,
*   'maxX': 1,
*   'stepX': 0,
*   'y': 0.5,  // initial y value
*   'minY': 0,
*   'maxY': 1,
*   'stepY': 0
* })
*
* @output
* change
* Fires any time the interface's value changes. <br>
* The event data is an object with x and y properties containing the x and y values of the interface.
*
* @outputexample
* position.on('change',function(v) {
*   console.log(v);
* })
*
*
*/

export default class Position extends Interface {

  constructor() {

    let options = ['value'];

    let defaults = {
      'size': [200,200],
      'mode': 'absolute',
      'minX': 0,
      'maxX': 1,
      'stepX': 0,
      'x': 0.5,
      'minY': 0,
      'maxY': 1,
      'stepY': 0,
      'y': 0.5
    };

    super(arguments,options,defaults);


    this._x = new Step( this.settings.minX, this.settings.maxX, this.settings.stepX, this.settings.x );
    this._y = new Step( this.settings.minY, this.settings.maxY, this.settings.stepY, this.settings.y );

    this.position = {
      x: new Interaction.Handle(this.settings.mode,'horizontal',[0,this.width],[this.height,0]),
      y: new Interaction.Handle(this.settings.mode,'vertical',[0,this.width],[this.height,0])
    };
    this.position.x.value = this._x.normalized;
    this.position.y.value = this._y.normalized;

    this.init();
    this.render();

  }

  buildInterface() {

    this.knob = svg.create('circle');
    this.element.appendChild(this.knob);
    
  }

  sizeInterface() {

      this.position.x.resize([0,this.width],[this.height,0]);
      this.position.y.resize([0,this.width],[this.height,0]);

      this._minDimension = Math.min(this.width,this.height);

      this.knobRadius = {
        off: ~~(this._minDimension/100) * 5 + 5,
      };
      this.knobRadius.on = this.knobRadius.off * 2;

      this.knob.setAttribute('cx',this.width/2);
      this.knob.setAttribute('cy',this.height/2);
      this.knob.setAttribute('r',this.knobRadius.off);
  }

  colorInterface() {
      this.element.style.backgroundColor = this.colors.fill;
      this.knob.setAttribute('fill', this.colors.accent);
  }

  render() {
    if (this.clicked) {
    //  this.knobRadius = 30;
      this.knob.setAttribute('r',this.knobRadius.on);
    } else {
    //  this.knobRadius = 15;
      this.knob.setAttribute('r',this.knobRadius.off);
    }

    this.knobCoordinates = {
      x: this._x.normalized * this.width,
      y: this.height - this._y.normalized * this.height
    };

    this.knob.setAttribute('cx',this.knobCoordinates.x);
    this.knob.setAttribute('cy',this.knobCoordinates.y);
  }


  click() {
    this.position.x.anchor = this.mouse;
    this.position.y.anchor = this.mouse;
    this.move();
  }

  move() {
    if (this.clicked) {
      this.position.x.update(this.mouse);
      this.position.y.update(this.mouse);
      this._x.updateNormal( this.position.x.value );
      this._y.updateNormal( this.position.y.value );
      this.emit('change',{
        x: this._x.value,
        y: this._y.value
      });
      this.render();
    }
  }

  release() {
    this.render();
  }

  /**
  * The interface's x value. When set, it will automatically adjust to fit min/max/step settings of the interface.
  * @type {object}
  * @example position.x = 0.5;
  */

  get x() {
    return this._x.value;
  }

  set x(value) {
    this._x.update(value);
    this.emit('change',{
      x: this._x.value,
      y: this._y.value
    });
    this.render();
  }

  /**
  * The interface's y values. When set, it will automatically adjust to fit min/max/step settings of the interface.
  * @type {object}
  * @example position.x = 0.5;
  */

  get y() {
    return this._y.value;
  }

  set y(value) {
    this._y.update(value);
    this.emit('change',{
      x: this._x.value,
      y: this._y.value
    });
    this.render();
  }



  get normalized() {
    return {
      x: this._x.normalized,
      y: this._y.normalized
    };
  }

  /**
  * The lower limit of value on the x axis
  * @type {object}
  */
  get minX() {
    return this._x.min;
  }

  set minX(v) {
    this._x.min = v;
    this.render();
  }

  /**
  * The lower limit of value on the y axis
  * @type {object}
  */
  get minY() {
    return this._y.min;
  }

  set minY(v) {
    this._y.min = v;
    this.render();
  }


  /**
  * The upper limit of value on the x axis
  * @type {object}
  */
  get maxX() {
    return this._x.max;
  }

  set maxX(v) {
    this._x.max = v;
    this.render();
  }


  /**
  * The upper limit of value on the y axis
  * @type {object}
  */
  get maxY() {
    return this._y.max;
  }

  set maxY(v) {
    this._y.max = v;
    this.render();
  }


  /**
  * The incremental step of values on the x axis
  * @type {object}
  */
  get stepX() {
    return this._x.step;
  }

  set stepX(v) {
    this._x.step = v;
    this.render();
  }


  /**
  * The incremental step of values on the y axis
  * @type {object}
  */
  get stepY() {
    return this._y.step;
  }

  set stepY(v) {
    this._y.step = v;
    this.render();
  }


  /**
  Absolute mode (position's value jumps to mouse click position) or relative mode (mouse drag changes value relative to its current position). Default: "absolute".
  @type {string}
  @example position.mode = "relative";
  */
  get mode() {
    return this.position.x.mode;
  }
  set mode(v) {
    this.position.x.mode = v;
    this.position.y.mode = v;
  }




}