import is from '@pilotlab/is'; import { IAnimationEaseFunction } from '@pilotlab/animation'; import RangeScaleBase from './rangeScaleBase'; export class RangeScale extends RangeScaleBase { constructor( inputMin:number = 0, inputMax:number = 1, outputMin:number = 0, outputMax:number = 1, ease?:IAnimationEaseFunction ) { super(inputMin, inputMax, ease); let isInvert:boolean = outputMin > outputMax; let outputMinFinal:number = isInvert ? outputMax : outputMin; let outputMaxFinal:number = isInvert ? outputMin : outputMax; if (is.notEmpty(outputMinFinal)) this._outputMin = outputMinFinal; if (is.notEmpty(outputMaxFinal)) this._outputMax = outputMaxFinal; this._isInvert = isInvert; } /*--------------------------------------------------------------------* START: Static Methods *--------------------------------------------------------------------*/ /** * Returns the relative position of the input value * within the min/max range as a value between 0.0 and 1.0. */ static normalize(value:number, min:number, max:number, isConstrain:boolean = true, isInvert:boolean = false):number { let p:number = (value - min) / (max - min); if (isConstrain) { if (p < 0) p = 0; if (p > 1) p = 1; } if (isInvert) p = 1.0 - p; return p; } /** * Accepts a value between 0.0 and 1.0 and returns the input value at the corresponding * progress point within the min/max input range. */ static unnormalize(valueNormalized:number, min:number, max:number, isConstrain:boolean = true, isInvert:boolean = false):number { let p:number = valueNormalized; if (isConstrain) { if (p < 0) p = 0; if (p > 1) p = 1; } if (isInvert) p = 1.0 - p; return (min + (p * (max - min))); } static outputEase(value:number, min:number, max:number, ease:IAnimationEaseFunction):number { if (min > max) return ease(value - min, max, min - max, max - min); else return ease(value - min, min, max - min, max - min); } static easeNormalized(value:number, ease:IAnimationEaseFunction, isInvert:boolean = false):number { if (isInvert) value = 1.0 - value; return ease(value, 0, 1, 1); } /*--------------------------------------------------------------------* START: Properties *--------------------------------------------------------------------*/ get outputMin():number { return this._outputMin; } set outputMin(value:number) { this._outputMin = value; } private _outputMin:number = 0.0; get outputMax():number { return this._outputMax; } set outputMax(value:number) { this._outputMax = value; } private _outputMax:number = 0.0; get isInvert():boolean { return this._isInvert; } set isInvert(value:boolean) { this._isInvert = value; } private _isInvert:boolean = false; get value():number { return this._value; } private _value:number; /*--------------------------------------------------------------------* START: Public Methods *--------------------------------------------------------------------*/ output( inputValue:number, isValueNormalized:boolean = false, isConstrain:boolean = true, isNormalizeReturnValue:boolean = false, isInvertReturnValue:boolean = false ):number { //----- Make sure we have a raw (not normalized or constrained) input value to work with. if (isValueNormalized) inputValue = this.unnormalizeInput(inputValue, false); if (inputValue === this.p_lastInputRaw) return this._value; this.p_lastInputRaw = inputValue; this.p_checkInputPreviousRaw(inputValue); //----- Now get the raw, unconstrained output value. let p:number = this.normalizeInput(inputValue, false); let value:number = this._outputFromNormalized(p); //----- Find the return value. value = this.normalizeOutput(value, isConstrain, isInvertReturnValue); if (is.notEmpty(this.p_ease)) value = RangeScale.easeNormalized(value, this.p_ease); if (this._isInvert) value = 1.0 - value; this.p_lastInputNormalized = value; if (!isNormalizeReturnValue) value = this.unnormalizeOutput(value); //----- Store the value for possible later retrieval. this._value = value; return value } /*--------------------------------------------------------------------* START: Public Methods *--------------------------------------------------------------------*/ /** * Returns the relative position of the output value * within the min/max range as a value between 0.0 and 1.0. */ normalizeOutput(outputUnnormalized:number, isConstrain:boolean = true, isInvert:boolean = false):number { return RangeScale.normalize(outputUnnormalized, this._outputMin, this._outputMax, isConstrain, isInvert); } /** * Accepts a value between 0.0 and 1.0 and returns the output value * at the corresponding progress point within the min/max input range. */ unnormalizeOutput(outputNormalized:number, isConstrain:boolean = true, isInvert:boolean = false):number { return RangeScale.unnormalize(outputNormalized, this._outputMin, this._outputMax, isConstrain, isInvert); } /*--------------------------------------------------------------------* START: Private Methods *--------------------------------------------------------------------*/ private _outputFromNormalized(inputNormalized:number):number { let p:number = inputNormalized; return (this._outputMin + (p * (this._outputMax - this._outputMin))); } } // End class export default RangeScale;