⌈⌋ ⎇ branch:  Bitrhythm


Artifact Content

Artifact 248162886ed51588cbb33a980c649f9aa785a71d73d2843c5e17ada967adb2ee:


'use strict';

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

/**
* Slider
*
* @description Horizontal or vertical slider with settable interaction modes.
*
* @demo <span nexus-ui="slider" step=0.2></span>
*
* @example
* var slider = new Nexus.Slider('#target')
*
* @example
* var slider = new Nexus.Slider('#target',{
*     'size': [120,20],
*     'mode': 'relative',  // 'relative' or 'absolute'
*     'min': 0,
*     'max': 1,
*     'step': 0,
*     'value': 0
* })
*
* @output
* change
* Fires when the interface's value changes. <br>
* Event data: <i>number</i> The number value of the interface.
*
* @outputexample
* slider.on('change',function(v) {
*   console.log(v);
* })
*
*
*/

export default class Slider extends Interface {

  constructor() {

    let options = ['min','max','value'];

    let defaults = {
      'size': [120,20],
      'mode': 'relative',  // 'relative' or 'absolute'
      'min': 0,
      'max': 1,
      'step': 0,
      'value': 0
    };

    super(arguments,options,defaults);

    this.orientation = 'vertical'; // This will change automatically to 'horizontal'if the interface is wider than it is tall.

    this._value = new Step(this.settings.min, this.settings.max, this.settings.step, this.settings.value);

    this.position = new Interaction.Handle(this.settings.mode,this.orientation,[0,this.width],[this.height,0]);
    this.position.value = this._value.normalized;

    this.init();

    this.position.direction = this.orientation;

    this.emit('change',this.value);

  }

  buildInterface() {

    this.bar = svg.create('rect');
    this.fillbar = svg.create('rect');
    this.knob = svg.create('circle');

    this.element.appendChild(this.bar);
    this.element.appendChild(this.fillbar);
    this.element.appendChild(this.knob);

  }

  sizeInterface() {

    if (this.width < this.height) {
      this.orientation = 'vertical';
      this.position.direction = 'vertical';
    } else {
      this.orientation = 'horizontal';
      this.position.direction = 'horizontal';
    }

    if (this.position) {
      this.position.resize([0,this.width],[this.height,0]);
    }

    let x, y, w, h, barOffset, cornerRadius;
    this.knobData = {
      level: 0,
      r: 0
    };

    if (this.orientation === 'vertical') {
      this.thickness = this.width / 2;
    	x = this.width/2;
    	y = 0;
    	w = this.thickness;
    	h = this.height;
      this.knobData.r = this.thickness * 0.8;
    	this.knobData.level = h-this.knobData.r-this.normalized*(h-this.knobData.r*2);
      barOffset = 'translate('+this.thickness*(-1)/2+',0)';
      cornerRadius = w/2;
    } else {
      this.thickness = this.height / 2;
    	x = 0;
    	y = this.height/2;
    	w = this.width;
    	h = this.thickness;
      this.knobData.r = this.thickness * 0.8;
    	this.knobData.level = this.normalized*(w-this.knobData.r*2)+this.knobData.r;
      barOffset = 'translate(0,'+this.thickness*(-1)/2+')';
      cornerRadius = h/2;
    }

    this.bar.setAttribute('x',x);
    this.bar.setAttribute('y',y);
    this.bar.setAttribute('transform',barOffset);
    this.bar.setAttribute('rx',cornerRadius); // corner radius
    this.bar.setAttribute('ry',cornerRadius);
    this.bar.setAttribute('width',w);
    this.bar.setAttribute('height',h);

    if (this.orientation === 'vertical') {
      this.fillbar.setAttribute('x',x);
      this.fillbar.setAttribute('y',this.knobData.level);
      this.fillbar.setAttribute('width',w);
      this.fillbar.setAttribute('height',h-this.knobData.level);
    } else {
      this.fillbar.setAttribute('x',0);
      this.fillbar.setAttribute('y',y);
      this.fillbar.setAttribute('width',this.knobData.level);
      this.fillbar.setAttribute('height',h);
    }
    this.fillbar.setAttribute('transform',barOffset);
    this.fillbar.setAttribute('rx',cornerRadius);
    this.fillbar.setAttribute('ry',cornerRadius);

    if (this.orientation === 'vertical') {
      this.knob.setAttribute('cx',x);
      this.knob.setAttribute('cy',this.knobData.level);
    } else {
      this.knob.setAttribute('cx',this.knobData.level);
      this.knob.setAttribute('cy',y);
    }
    this.knob.setAttribute('r',this.knobData.r);

  }

  colorInterface() {
    this.bar.setAttribute('fill', this.colors.fill);
    this.fillbar.setAttribute('fill', this.colors.accent);
    this.knob.setAttribute('fill', this.colors.accent);
  }


  render() {
    if (!this.clicked) {
      this.knobData.r = this.thickness*0.75;
    }
    this.knob.setAttribute('r',this.knobData.r);

    if (this.orientation === 'vertical') {
  	   this.knobData.level = this.knobData.r+this._value.normalized*(this.height-this.knobData.r*2);
       this.knob.setAttribute('cy',this.height - this.knobData.level);
       this.fillbar.setAttribute('y',this.height - this.knobData.level);
       this.fillbar.setAttribute('height',this.knobData.level);
    } else {
  	   this.knobData.level = this._value.normalized*(this.width-this.knobData.r*2)+this.knobData.r;
       this.knob.setAttribute('cx',this.knobData.level);
       this.fillbar.setAttribute('x',0);
       this.fillbar.setAttribute('width',this.knobData.level);
    }
  }


  click() {
    this.knobData.r = this.thickness*0.9;
    this.position.anchor = this.mouse;
    this.move();
  }

  move() {
    if (this.clicked) {
      this.position.update(this.mouse);
      this._value.updateNormal( this.position.value );
      this.emit('change',this._value.value);
      this.render();

    }
  }

  release() {
    this.render();
  }

  get normalized() {
    return this._value.normalized;
  }

  /**
  The slider's current value. If set manually, will update the interface and trigger the output event.
  @type {number}
  @example slider.value = 10;
  */
  get value() {
    return this._value.value;
  }
  set value(v) {
    this._value.update(v);
    this.position.value = this._value.normalized;
    this.emit('change',this._value.value);
    this.render();
  }

  /**
  Lower limit of the sliders's output range
  @type {number}
  @example slider.min = 1000;
  */
  get min() {
    return this._value.min;
  }
  set min(v) {
    this._value.min = v;
  }

  /**
  Upper limit of the slider's output range
  @type {number}
  @example slider.max = 1000;
  */
  get max() {
    return this._value.max;
  }
  set max(v) {
    this._value.max = v;
  }

  /**
  The increment that the slider's value changes by.
  @type {number}
  @example slider.step = 5;
  */
  get step() {
    return this._value.step;
  }
  set step(v) {
    this._value.step = v;
  }

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



}