/*
* The MIT License (MIT)
*
* Copyright (c) 2013, Christian Schudt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wallettemplate.utils.easing;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
/**
* This interpolator simulates an elastic behavior.
* <p/>
* The following curve illustrates the interpolation.
* </p>
* <svg style="width:300px;" xmlns="http://www.w3.org/2000/svg" viewBox="-2 -40 124 140">
* <line style="stroke: rgb(187, 187, 187); stroke-width: 1px;" y2="60" y1="0" x2="0" x1="0"/>
* <text style="font-size: 12px; fill: rgb(187, 187, 187);" y="6" x="2">x</text>
* <line style="stroke: rgb(187, 187, 187); stroke-width: 1px;" y2="60" y1="60" x2="120" x1="0"/>
* <text style="font-size: 12px; fill: rgb(187, 187, 187);" y="57" x="115">t</text>
* <path style="fill: rgba(255, 255, 255, 0);stroke: black;stroke-width: 2px;"
* d="M0,60 L1.2,54.8 2.4,47.7 3.6,39.4 4.8,30.4 6.0,21.2 7.2,12.2 8.4,3.9 9.6,-3.6 10.8,-9.9 12.0,-15.0 13.2,-18.7 14.4,-21.1 15.6,-22.3 16.8,-22.2 18.0,-21.2 19.2,-19.4 20.4,-16.9 21.6,-13.9 22.8,-10.8 24.0,-7.5 25.2,-4.3 26.4,-1.4 27.6,1.3 28.8,3.5 30.0,5.3 31.2,6.6 32.4,7.5 33.6,7.9 34.8,7.9 36.0,7.5 37.2,6.8 38.4,6.0 39.6,4.9 40.8,3.8 42.0,2.7 43.2,1.5 44.4,0.5 45.6,-0.5 46.8,-1.2 48.0,-1.9 49.2,-2.3 50.4,-2.6 51.6,-2.8 52.8,-2.8 54.0,-2.7 55.2,-2.4 56.4,-2.1 57.6,-1.7 58.8,-1.3 60.0,-0.9 61.2,-0.5 62.4,-0.2 63.6,0.2 64.8,0.4 66.0,0.7 67.2,0.8 68.4,0.9 69.6,1.0 70.8,1.0 72.0,0.9 73.2,0.9 74.4,0.7 75.6,0.6 76.8,0.5 78.0,0.3 79.2,0.2 80.4,0.1 81.6,-0.1 82.8,-0.2 84.0,-0.2 85.2,-0.3 86.4,-0.3 87.6,-0.3 88.8,-0.3 90.0,-0.3 91.2,-0.3 92.4,-0.3 93.6,-0.2 94.8,-0.2 96.0,-0.1 97.2,-0.1 98.4,-0.0 99.6,0.0 100.8,0.1 102.0,0.1 103.2,0.1 104.4,0.1 105.6,0.1 106.8,0.1 108.0,0.1 109.2,0.1 110.4,0.1 111.6,0.1 112.8,0.1 114.0,0.0 115.2,0.0 116.4,0.0 117.6,-0.0 118.8,-0.0 120.0,0.0"/>
* </svg>
* <p/>
* The math in this class is taken from
* <a href="http://www.robertpenner.com/easing/">http://www.robertpenner.com/easing/</a>.
*
* @author Christian Schudt
*/
public class ElasticInterpolator extends EasingInterpolator {
/**
* The amplitude.
*/
private DoubleProperty amplitude = new SimpleDoubleProperty(this, "amplitude", 1);
/**
* The number of oscillations.
*/
private DoubleProperty oscillations = new SimpleDoubleProperty(this, "oscillations", 3);
/**
* Default constructor. Initializes the interpolator with ease out mode.
*/
public ElasticInterpolator() {
this(EasingMode.EASE_OUT);
}
/**
* Constructs the interpolator with a specific easing mode.
*
* @param easingMode The easing mode.
*/
public ElasticInterpolator(EasingMode easingMode) {
super(easingMode);
}
/**
* Sets the easing mode.
*
* @param easingMode The easing mode.
* @see #easingModeProperty()
*/
public ElasticInterpolator(EasingMode easingMode, double amplitude, double oscillations) {
super(easingMode);
this.amplitude.set(amplitude);
this.oscillations.set(oscillations);
}
/**
* The oscillations property. Defines number of oscillations.
*
* @return The property.
* @see #getOscillations()
* @see #setOscillations(double)
*/
public DoubleProperty oscillationsProperty() {
return oscillations;
}
/**
* The amplitude. The minimum value is 1. If this value is < 1 it will be set to 1 during animation.
*
* @return The property.
* @see #getAmplitude()
* @see #setAmplitude(double)
*/
public DoubleProperty amplitudeProperty() {
return amplitude;
}
/**
* Gets the amplitude.
*
* @return The amplitude.
* @see #amplitudeProperty()
*/
public double getAmplitude() {
return amplitude.get();
}
/**
* Sets the amplitude.
*
* @param amplitude The amplitude.
* @see #amplitudeProperty()
*/
public void setAmplitude(final double amplitude) {
this.amplitude.set(amplitude);
}
/**
* Gets the number of oscillations.
*
* @return The oscillations.
* @see #oscillationsProperty()
*/
public double getOscillations() {
return oscillations.get();
}
/**
* Sets the number of oscillations.
*
* @param oscillations The oscillations.
* @see #oscillationsProperty()
*/
public void setOscillations(final double oscillations) {
this.oscillations.set(oscillations);
}
@Override
protected double baseCurve(double v) {
if (v == 0) {
return 0;
}
if (v == 1) {
return 1;
}
double p = 1.0 / oscillations.get();
double a = amplitude.get();
double s;
if (a < Math.abs(1)) {
a = 1;
s = p / 4;
} else {
s = p / (2 * Math.PI) * Math.asin(1 / a);
}
return -(a * Math.pow(2, 10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / p));
}
}