From 099ad23a0a6ab294f8c96ee1f3573ddbfafb4bd7 Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Tue, 9 Dec 2025 09:48:43 +0100 Subject: [PATCH] Kotlin animation --- .../charting/animation/ChartAnimator.java | 207 ------------ .../charting/animation/ChartAnimator.kt | 190 +++++++++++ .../mikephil/charting/animation/Easing.java | 309 ----------------- .../mikephil/charting/animation/Easing.kt | 315 ++++++++++++++++++ .../chartexample/HalfPieChartActivity.kt | 2 +- .../appdev/chartexample/LineChartActivity.kt | 2 +- .../appdev/chartexample/PieChartActivity.kt | 4 +- .../chartexample/PieChartRoundedActivity.kt | 4 +- .../chartexample/PiePolylineChartActivity.kt | 4 +- .../appdev/chartexample/RadarChartActivity.kt | 4 +- .../SpecificPositionsLineChartActivity.kt | 2 +- 11 files changed, 516 insertions(+), 527 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.kt delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.kt diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java deleted file mode 100644 index e5b82db0b6..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.github.mikephil.charting.animation; - -import android.animation.ObjectAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; -import androidx.annotation.RequiresApi; - -import com.github.mikephil.charting.animation.Easing.EasingFunction; - -/** - * Object responsible for all animations in the Chart. Animations require API level 11. - * - * @author Philipp Jahoda - * @author Mick Ashton - */ -public class ChartAnimator { - - /** object that is updated upon animation update */ - private AnimatorUpdateListener mListener; - - /** The phase of drawn values on the y-axis. 0 - 1 */ - @SuppressWarnings("WeakerAccess") - protected float mPhaseY = 1f; - - /** The phase of drawn values on the x-axis. 0 - 1 */ - @SuppressWarnings("WeakerAccess") - protected float mPhaseX = 1f; - - public ChartAnimator() { } - - @RequiresApi(11) - public ChartAnimator(AnimatorUpdateListener listener) { - mListener = listener; - } - - @RequiresApi(11) - private ObjectAnimator xAnimator(int duration, EasingFunction easing) { - - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(easing); - animatorX.setDuration(duration); - - return animatorX; - } - - @RequiresApi(11) - private ObjectAnimator yAnimator(int duration, EasingFunction easing) { - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(easing); - animatorY.setDuration(duration); - - return animatorY; - } - - /** - * Animates values along the X axis, in a linear fashion. - * - * @param durationMillis animation duration - */ - @RequiresApi(11) - public void animateX(int durationMillis) { - animateX(durationMillis, Easing.Linear); - } - - /** - * Animates values along the X axis. - * - * @param durationMillis animation duration - * @param easing EasingFunction - */ - @RequiresApi(11) - public void animateX(int durationMillis, EasingFunction easing) { - - ObjectAnimator animatorX = xAnimator(durationMillis, easing); - animatorX.addUpdateListener(mListener); - animatorX.start(); - } - - /** - * Animates values along both the X and Y axes, in a linear fashion. - * - * @param durationMillisX animation duration along the X axis - * @param durationMillisY animation duration along the Y axis - */ - @RequiresApi(11) - public void animateXY(int durationMillisX, int durationMillisY) { - animateXY(durationMillisX, durationMillisY, Easing.Linear, Easing.Linear); - } - - /** - * Animates values along both the X and Y axes. - * - * @param durationMillisX animation duration along the X axis - * @param durationMillisY animation duration along the Y axis - * @param easing EasingFunction for both axes - */ - @RequiresApi(11) - public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easing) { - - ObjectAnimator xAnimator = xAnimator(durationMillisX, easing); - ObjectAnimator yAnimator = yAnimator(durationMillisY, easing); - - if (durationMillisX > durationMillisY) { - xAnimator.addUpdateListener(mListener); - } else { - yAnimator.addUpdateListener(mListener); - } - - xAnimator.start(); - yAnimator.start(); - } - - /** - * Animates values along both the X and Y axes. - * - * @param durationMillisX animation duration along the X axis - * @param durationMillisY animation duration along the Y axis - * @param easingX EasingFunction for the X axis - * @param easingY EasingFunction for the Y axis - */ - @RequiresApi(11) - public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, - EasingFunction easingY) { - - ObjectAnimator xAnimator = xAnimator(durationMillisX, easingX); - ObjectAnimator yAnimator = yAnimator(durationMillisY, easingY); - - if (durationMillisX > durationMillisY) { - xAnimator.addUpdateListener(mListener); - } else { - yAnimator.addUpdateListener(mListener); - } - - xAnimator.start(); - yAnimator.start(); - } - - /** - * Animates values along the Y axis, in a linear fashion. - * - * @param durationMillis animation duration - */ - @RequiresApi(11) - public void animateY(int durationMillis) { - animateY(durationMillis, Easing.Linear); - } - - /** - * Animates values along the Y axis. - * - * @param durationMillis animation duration - * @param easing EasingFunction - */ - @RequiresApi(11) - public void animateY(int durationMillis, EasingFunction easing) { - - ObjectAnimator animatorY = yAnimator(durationMillis, easing); - animatorY.addUpdateListener(mListener); - animatorY.start(); - } - - /** - * Gets the Y axis phase of the animation. - * - * @return float value of {@link #mPhaseY} - */ - public float getPhaseY() { - return mPhaseY; - } - - /** - * Sets the Y axis phase of the animation. - * - * @param phase float value between 0 - 1 - */ - public void setPhaseY(float phase) { - if (phase > 1f) { - phase = 1f; - } else if (phase < 0f) { - phase = 0f; - } - mPhaseY = phase; - } - - /** - * Gets the X axis phase of the animation. - * - * @return float value of {@link #mPhaseX} - */ - public float getPhaseX() { - return mPhaseX; - } - - /** - * Sets the X axis phase of the animation. - * - * @param phase float value between 0 - 1 - */ - public void setPhaseX(float phase) { - if (phase > 1f) { - phase = 1f; - } else if (phase < 0f) { - phase = 0f; - } - mPhaseX = phase; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.kt new file mode 100644 index 0000000000..1da8cbcb36 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.kt @@ -0,0 +1,190 @@ +package com.github.mikephil.charting.animation + +import android.animation.ObjectAnimator +import android.animation.ValueAnimator.AnimatorUpdateListener +import androidx.annotation.RequiresApi +import com.github.mikephil.charting.animation.Easing.EasingFunction + +/** + * Object responsible for all animations in the Chart. Animations require API level 11. + */ +class ChartAnimator { + /** object that is updated upon animation update */ + private var animatorUpdateListener: AnimatorUpdateListener? = null + + /** The phase of drawn values on the y-axis. 0 - 1 */ + protected var mPhaseY: Float = 1f + + /** The phase of drawn values on the x-axis. 0 - 1 */ + protected var mPhaseX: Float = 1f + + constructor() + + @RequiresApi(11) + constructor(listener: AnimatorUpdateListener?) { + animatorUpdateListener = listener + } + + @RequiresApi(11) + private fun xAnimator(duration: Int, easing: EasingFunction?): ObjectAnimator { + val animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f) + animatorX.interpolator = easing + animatorX.duration = duration.toLong() + + return animatorX + } + + @RequiresApi(11) + private fun yAnimator(duration: Int, easing: EasingFunction?): ObjectAnimator { + val animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f) + animatorY.interpolator = easing + animatorY.duration = duration.toLong() + + return animatorY + } + + /** + * Animates values along the X axis, in a linear fashion. + * + * @param durationMillis animation duration + */ + @RequiresApi(11) + fun animateX(durationMillis: Int) { + animateX(durationMillis, Easing.linear) + } + + /** + * Animates values along the X axis. + * + * @param durationMillis animation duration + * @param easing EasingFunction + */ + @RequiresApi(11) + fun animateX(durationMillis: Int, easing: EasingFunction?) { + val animatorX = xAnimator(durationMillis, easing) + animatorX.addUpdateListener(animatorUpdateListener) + animatorX.start() + } + + /** + * Animates values along both the X and Y axes, in a linear fashion. + * + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis + */ + @RequiresApi(11) + fun animateXY(durationMillisX: Int, durationMillisY: Int) { + animateXY(durationMillisX, durationMillisY, Easing.linear, Easing.linear) + } + + /** + * Animates values along both the X and Y axes. + * + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis + * @param easing EasingFunction for both axes + */ + @RequiresApi(11) + fun animateXY(durationMillisX: Int, durationMillisY: Int, easing: EasingFunction?) { + val xAnimator = xAnimator(durationMillisX, easing) + val yAnimator = yAnimator(durationMillisY, easing) + + if (durationMillisX > durationMillisY) { + xAnimator.addUpdateListener(animatorUpdateListener) + } else { + yAnimator.addUpdateListener(animatorUpdateListener) + } + + xAnimator.start() + yAnimator.start() + } + + /** + * Animates values along both the X and Y axes. + * + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis + * @param easingX EasingFunction for the X axis + * @param easingY EasingFunction for the Y axis + */ + @RequiresApi(11) + fun animateXY( + durationMillisX: Int, durationMillisY: Int, easingX: EasingFunction?, + easingY: EasingFunction? + ) { + val xAnimator = xAnimator(durationMillisX, easingX) + val yAnimator = yAnimator(durationMillisY, easingY) + + if (durationMillisX > durationMillisY) { + xAnimator.addUpdateListener(animatorUpdateListener) + } else { + yAnimator.addUpdateListener(animatorUpdateListener) + } + + xAnimator.start() + yAnimator.start() + } + + /** + * Animates values along the Y axis, in a linear fashion. + * + * @param durationMillis animation duration + */ + @RequiresApi(11) + fun animateY(durationMillis: Int) { + animateY(durationMillis, Easing.linear) + } + + /** + * Animates values along the Y axis. + * + * @param durationMillis animation duration + * @param easing EasingFunction + */ + @RequiresApi(11) + fun animateY(durationMillis: Int, easing: EasingFunction?) { + val animatorY = yAnimator(durationMillis, easing) + animatorY.addUpdateListener(animatorUpdateListener) + animatorY.start() + } + + var phaseY: Float + /** + * Gets the Y axis phase of the animation. + */ + get() = mPhaseY + /** + * Sets the Y axis phase of the animation. + * + * @param phase float value between 0 - 1 + */ + set(phase) { + var phase = phase + if (phase > 1f) { + phase = 1f + } else if (phase < 0f) { + phase = 0f + } + mPhaseY = phase + } + + var phaseX: Float + /** + * Gets the X axis phase of the animation. + */ + get() = mPhaseX + /** + * Sets the X axis phase of the animation. + * + * @param phase float value between 0 - 1 + */ + set(phase) { + var phase = phase + if (phase > 1f) { + phase = 1f + } else if (phase < 0f) { + phase = 0f + } + mPhaseX = phase + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java deleted file mode 100644 index acb7dcc965..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java +++ /dev/null @@ -1,309 +0,0 @@ -package com.github.mikephil.charting.animation; - -import android.animation.TimeInterpolator; -import androidx.annotation.RequiresApi; - -/** - * Easing options. - * - * @author Daniel Cohen Gindi - * @author Mick Ashton - */ -@SuppressWarnings("WeakerAccess") -@RequiresApi(11) -public class Easing { - - public interface EasingFunction extends TimeInterpolator { - @Override - float getInterpolation(float input); - } - - private static final float DOUBLE_PI = 2f * (float) Math.PI; - - @SuppressWarnings("unused") - public static final EasingFunction Linear = new EasingFunction() { - public float getInterpolation(float input) { - return input; - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInQuad = new EasingFunction() { - public float getInterpolation(float input) { - return input * input; - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutQuad = new EasingFunction() { - public float getInterpolation(float input) { - return -input * (input - 2f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutQuad = new EasingFunction() { - public float getInterpolation(float input) { - input *= 2f; - - if (input < 1f) { - return 0.5f * input * input; - } - - return -0.5f * ((--input) * (input - 2f) - 1f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInCubic = new EasingFunction() { - public float getInterpolation(float input) { - return (float) Math.pow(input, 3); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutCubic = new EasingFunction() { - public float getInterpolation(float input) { - input--; - return (float) Math.pow(input, 3) + 1f; - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutCubic = new EasingFunction() { - public float getInterpolation(float input) { - input *= 2f; - if (input < 1f) { - return 0.5f * (float) Math.pow(input, 3); - } - input -= 2f; - return 0.5f * ((float) Math.pow(input, 3) + 2f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInQuart = new EasingFunction() { - - public float getInterpolation(float input) { - return (float) Math.pow(input, 4); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutQuart = new EasingFunction() { - public float getInterpolation(float input) { - input--; - return -((float) Math.pow(input, 4) - 1f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutQuart = new EasingFunction() { - public float getInterpolation(float input) { - input *= 2f; - if (input < 1f) { - return 0.5f * (float) Math.pow(input, 4); - } - input -= 2f; - return -0.5f * ((float) Math.pow(input, 4) - 2f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInSine = new EasingFunction() { - public float getInterpolation(float input) { - return -(float) Math.cos(input * (Math.PI / 2f)) + 1f; - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutSine = new EasingFunction() { - public float getInterpolation(float input) { - return (float) Math.sin(input * (Math.PI / 2f)); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutSine = new EasingFunction() { - public float getInterpolation(float input) { - return -0.5f * ((float) Math.cos(Math.PI * input) - 1f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInExpo = new EasingFunction() { - public float getInterpolation(float input) { - return (input == 0) ? 0f : (float) Math.pow(2f, 10f * (input - 1f)); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutExpo = new EasingFunction() { - public float getInterpolation(float input) { - return (input == 1f) ? 1f : (-(float) Math.pow(2f, -10f * (input + 1f))); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutExpo = new EasingFunction() { - public float getInterpolation(float input) { - if (input == 0) { - return 0f; - } else if (input == 1f) { - return 1f; - } - - input *= 2f; - if (input < 1f) { - return 0.5f * (float) Math.pow(2f, 10f * (input - 1f)); - } - return 0.5f * (-(float) Math.pow(2f, -10f * --input) + 2f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInCirc = new EasingFunction() { - public float getInterpolation(float input) { - return -((float) Math.sqrt(1f - input * input) - 1f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutCirc = new EasingFunction() { - public float getInterpolation(float input) { - input--; - return (float) Math.sqrt(1f - input * input); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutCirc = new EasingFunction() { - public float getInterpolation(float input) { - input *= 2f; - if (input < 1f) { - return -0.5f * ((float) Math.sqrt(1f - input * input) - 1f); - } - return 0.5f * ((float) Math.sqrt(1f - (input -= 2f) * input) + 1f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInElastic = new EasingFunction() { - public float getInterpolation(float input) { - if (input == 0) { - return 0f; - } else if (input == 1) { - return 1f; - } - - float p = 0.3f; - float s = p / DOUBLE_PI * (float) Math.asin(1f); - return -((float) Math.pow(2f, 10f * (input -= 1f)) - *(float) Math.sin((input - s) * DOUBLE_PI / p)); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutElastic = new EasingFunction() { - public float getInterpolation(float input) { - if (input == 0) { - return 0f; - } else if (input == 1) { - return 1f; - } - - float p = 0.3f; - float s = p / DOUBLE_PI * (float) Math.asin(1f); - return 1f - + (float) Math.pow(2f, -10f * input) - * (float) Math.sin((input - s) * DOUBLE_PI / p); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutElastic = new EasingFunction() { - public float getInterpolation(float input) { - if (input == 0) { - return 0f; - } - - input *= 2f; - if (input == 2) { - return 1f; - } - - float p = 1f / 0.45f; - float s = 0.45f / DOUBLE_PI * (float) Math.asin(1f); - if (input < 1f) { - return -0.5f - * ((float) Math.pow(2f, 10f * (input -= 1f)) - * (float) Math.sin((input * 1f - s) * DOUBLE_PI * p)); - } - return 1f + 0.5f - * (float) Math.pow(2f, -10f * (input -= 1f)) - * (float) Math.sin((input * 1f - s) * DOUBLE_PI * p); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInBack = new EasingFunction() { - public float getInterpolation(float input) { - final float s = 1.70158f; - return input * input * ((s + 1f) * input - s); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutBack = new EasingFunction() { - public float getInterpolation(float input) { - final float s = 1.70158f; - input--; - return (input * input * ((s + 1f) * input + s) + 1f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutBack = new EasingFunction() { - public float getInterpolation(float input) { - float s = 1.70158f; - input *= 2f; - if (input < 1f) { - return 0.5f * (input * input * (((s *= (1.525f)) + 1f) * input - s)); - } - return 0.5f * ((input -= 2f) * input * (((s *= (1.525f)) + 1f) * input + s) + 2f); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInBounce = new EasingFunction() { - public float getInterpolation(float input) { - return 1f - EaseOutBounce.getInterpolation(1f - input); - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseOutBounce = new EasingFunction() { - public float getInterpolation(float input) { - float s = 7.5625f; - if (input < (1f / 2.75f)) { - return s * input * input; - } else if (input < (2f / 2.75f)) { - return s * (input -= (1.5f / 2.75f)) * input + 0.75f; - } else if (input < (2.5f / 2.75f)) { - return s * (input -= (2.25f / 2.75f)) * input + 0.9375f; - } - return s * (input -= (2.625f / 2.75f)) * input + 0.984375f; - } - }; - - @SuppressWarnings("unused") - public static final EasingFunction EaseInOutBounce = new EasingFunction() { - public float getInterpolation(float input) { - if (input < 0.5f) { - return EaseInBounce.getInterpolation(input * 2f) * 0.5f; - } - return EaseOutBounce.getInterpolation(input * 2f - 1f) * 0.5f + 0.5f; - } - }; - -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.kt b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.kt new file mode 100644 index 0000000000..04a447633b --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.kt @@ -0,0 +1,315 @@ +package com.github.mikephil.charting.animation + +import android.animation.TimeInterpolator +import androidx.annotation.RequiresApi +import kotlin.math.asin +import kotlin.math.cos +import kotlin.math.pow +import kotlin.math.sin +import kotlin.math.sqrt + +/** + * Easing options. + */ +@RequiresApi(11) +object Easing { + private const val DOUBLE_PI = 2f * Math.PI.toFloat() + + @Suppress("unused") + val linear: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return input + } + } + + @Suppress("unused") + val easeInQuad: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return input * input + } + } + + @Suppress("unused") + val easeOutQuad: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return -input * (input - 2f) + } + } + + @Suppress("unused") + val easeInOutQuad: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + input *= 2f + + if (input < 1f) { + return 0.5f * input * input + } + + return -0.5f * ((--input) * (input - 2f) - 1f) + } + } + + @Suppress("unused") + val easeInCubic: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return input.toDouble().pow(3.0).toFloat() + } + } + + @Suppress("unused") + val easeOutCubic: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + input-- + return input.toDouble().pow(3.0).toFloat() + 1f + } + } + + @Suppress("unused") + val easeInOutCubic: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + input *= 2f + if (input < 1f) { + return 0.5f * input.toDouble().pow(3.0).toFloat() + } + input -= 2f + return 0.5f * (input.toDouble().pow(3.0).toFloat() + 2f) + } + } + + @Suppress("unused") + val easeInQuart: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return input.toDouble().pow(4.0).toFloat() + } + } + + @Suppress("unused") + val easeOutQuart: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + input-- + return -(input.toDouble().pow(4.0).toFloat() - 1f) + } + } + + @Suppress("unused") + val easeInOutQuart: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + input *= 2f + if (input < 1f) { + return 0.5f * input.toDouble().pow(4.0).toFloat() + } + input -= 2f + return -0.5f * (input.toDouble().pow(4.0).toFloat() - 2f) + } + } + + @Suppress("unused") + val easeInSine: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return -cos(input * (Math.PI / 2f)).toFloat() + 1f + } + } + + @Suppress("unused") + val easeOutSine: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return sin(input * (Math.PI / 2f)).toFloat() + } + } + + @Suppress("unused") + val easeInOutSine: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return -0.5f * (cos(Math.PI * input).toFloat() - 1f) + } + } + + @Suppress("unused") + val easeInExpo: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return if (input == 0f) 0f else 2.0.pow((10f * (input - 1f)).toDouble()).toFloat() + } + } + + @Suppress("unused") + val easeOutExpo: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return if (input == 1f) 1f else (-2.0.pow((-10f * (input + 1f)).toDouble()).toFloat()) + } + } + + @Suppress("unused") + val easeInOutExpo: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + if (input == 0f) { + return 0f + } else if (input == 1f) { + return 1f + } + + input *= 2f + if (input < 1f) { + return 0.5f * 2.0.pow((10f * (input - 1f)).toDouble()).toFloat() + } + return 0.5f * (-2.0.pow((-10f * --input).toDouble()).toFloat() + 2f) + } + } + + @Suppress("unused") + val easeInCirc: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return -(sqrt((1f - input * input).toDouble()).toFloat() - 1f) + } + } + + @Suppress("unused") + val easeOutCirc: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + input-- + return sqrt((1f - input * input).toDouble()).toFloat() + } + } + + @Suppress("unused") + val easeInOutCirc: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + input *= 2f + if (input < 1f) { + return -0.5f * (sqrt((1f - input * input).toDouble()).toFloat() - 1f) + } + return 0.5f * (sqrt((1f - (2f.let { input -= it; input }) * input).toDouble()).toFloat() + 1f) + } + } + + @Suppress("unused") + val easeInElastic: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + if (input == 0f) { + return 0f + } else if (input == 1f) { + return 1f + } + + val p = 0.3f + val s = p / DOUBLE_PI * asin(1.0).toFloat() + return -(2.0.pow((10f * (1f.let { input -= it; input })).toDouble()).toFloat() * sin(((input - s) * DOUBLE_PI / p).toDouble()).toFloat()) + } + } + + @Suppress("unused") + val easeOutElastic: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + if (input == 0f) { + return 0f + } else if (input == 1f) { + return 1f + } + + val p = 0.3f + val s = p / DOUBLE_PI * asin(1.0).toFloat() + return (1f + 2.0.pow((-10f * input).toDouble()).toFloat() * sin(((input - s) * DOUBLE_PI / p).toDouble()).toFloat()) + } + } + + @Suppress("unused") + val easeInOutElastic: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + if (input == 0f) { + return 0f + } + + input *= 2f + if (input == 2f) { + return 1f + } + + val p = 1f / 0.45f + val s = 0.45f / DOUBLE_PI * asin(1.0).toFloat() + if (input < 1f) { + return (-0.5f + * (2.0.pow((10f * (1f.let { input -= it; input })).toDouble()) + .toFloat() * sin(((input * 1f - s) * DOUBLE_PI * p).toDouble()).toFloat())) + } + return 1f + (0.5f + * 2.0.pow((-10f * (1f.let { input -= it; input })).toDouble()).toFloat() * sin(((input * 1f - s) * DOUBLE_PI * p).toDouble()).toFloat()) + } + } + + @Suppress("unused") + val easeInBack: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + val s = 1.70158f + return input * input * ((s + 1f) * input - s) + } + } + + @Suppress("unused") + val easeOutBack: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + val s = 1.70158f + input-- + return (input * input * ((s + 1f) * input + s) + 1f) + } + } + + @Suppress("unused") + val easeInOutBack: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + var s = 1.70158f + input *= 2f + if (input < 1f) { + return 0.5f * (input * input * (((1.525f.let { s *= it; s }) + 1f) * input - s)) + } + return 0.5f * ((2f.let { input -= it; input }) * input * (((1.525f.let { s *= it; s }) + 1f) * input + s) + 2f) + } + } + + @Suppress("unused") + val easeInBounce: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + return 1f - easeOutBounce.getInterpolation(1f - input) + } + } + + @Suppress("unused") + val easeOutBounce: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + var input = input + val s = 7.5625f + if (input < (1f / 2.75f)) { + return s * input * input + } else if (input < (2f / 2.75f)) { + return s * (1.5f / 2.75f.let { input -= it; input }) * input + 0.75f + } else if (input < (2.5f / 2.75f)) { + return s * (2.25f / 2.75f.let { input -= it; input }) * input + 0.9375f + } + return s * (2.625f / 2.75f.let { input -= it; input }) * input + 0.984375f + } + } + + @Suppress("unused") + val easeInOutBounce: EasingFunction = object : EasingFunction { + override fun getInterpolation(input: Float): Float { + if (input < 0.5f) { + return easeInBounce.getInterpolation(input * 2f) * 0.5f + } + return easeOutBounce.getInterpolation(input * 2f - 1f) * 0.5f + 0.5f + } + } + + interface EasingFunction : TimeInterpolator { + override fun getInterpolation(input: Float): Float + } +} diff --git a/app/src/main/kotlin/info/appdev/chartexample/HalfPieChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/HalfPieChartActivity.kt index 83f05c253c..1fd2e785cf 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/HalfPieChartActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/HalfPieChartActivity.kt @@ -64,7 +64,7 @@ class HalfPieChartActivity : DemoBase() { setData(100f) - chart!!.animateY(1400, Easing.EaseInOutQuad) + chart!!.animateY(1400, Easing.easeInOutQuad) val l = chart!!.legend l.verticalAlignment = Legend.LegendVerticalAlignment.TOP diff --git a/app/src/main/kotlin/info/appdev/chartexample/LineChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/LineChartActivity.kt index 392eb24bd1..8b4732c355 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/LineChartActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/LineChartActivity.kt @@ -235,7 +235,7 @@ class LineChartActivity : DemoBase(), OnSeekBarChangeListener, OnChartValueSelec } R.id.animateX -> binding.chart1.animateX(2000) - R.id.animateY -> binding.chart1.animateY(2000, Easing.EaseInCubic) + R.id.animateY -> binding.chart1.animateY(2000, Easing.easeInCubic) R.id.animateXY -> binding.chart1.animateXY(2000, 2000) R.id.actionSave -> { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { diff --git a/app/src/main/kotlin/info/appdev/chartexample/PieChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/PieChartActivity.kt index 7918f0c119..cf202f08e6 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/PieChartActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/PieChartActivity.kt @@ -91,7 +91,7 @@ class PieChartActivity : DemoBase(), OnSeekBarChangeListener, OnChartValueSelect seekBarX!!.progress = 4 seekBarY!!.progress = 10 - chart!!.animateY(1400, Easing.EaseInOutQuad) + chart!!.animateY(1400, Easing.easeInOutQuad) // chart.spin(2000, 0, 360); val l = chart!!.legend @@ -242,7 +242,7 @@ class PieChartActivity : DemoBase(), OnSeekBarChangeListener, OnChartValueSelect } R.id.actionToggleSpin -> { - chart!!.spin(1000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.EaseInOutCubic) + chart!!.spin(1000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.easeInOutCubic) } R.id.actionSave -> { diff --git a/app/src/main/kotlin/info/appdev/chartexample/PieChartRoundedActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/PieChartRoundedActivity.kt index 0f5ab00fa4..00da33dafa 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/PieChartRoundedActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/PieChartRoundedActivity.kt @@ -93,7 +93,7 @@ class PieChartRoundedActivity : DemoBase(), OnSeekBarChangeListener, OnChartValu seekBarX!!.progress = 4 seekBarY!!.progress = 10 - chart!!.animateY(1400, Easing.EaseInOutQuad) + chart!!.animateY(1400, Easing.easeInOutQuad) // chart.spin(2000, 0, 360); val l = chart!!.legend @@ -247,7 +247,7 @@ class PieChartRoundedActivity : DemoBase(), OnSeekBarChangeListener, OnChartValu } R.id.actionToggleSpin -> { - chart!!.spin(1000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.EaseInOutCubic) + chart!!.spin(1000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.easeInOutCubic) } R.id.actionSave -> { diff --git a/app/src/main/kotlin/info/appdev/chartexample/PiePolylineChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/PiePolylineChartActivity.kt index a30249d4cd..99f07d48f6 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/PiePolylineChartActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/PiePolylineChartActivity.kt @@ -95,7 +95,7 @@ class PiePolylineChartActivity : DemoBase(), OnSeekBarChangeListener, OnChartVal seekBarX!!.progress = 4 seekBarY!!.progress = 100 - chart!!.animateY(1400, Easing.EaseInOutQuad) + chart!!.animateY(1400, Easing.easeInOutQuad) // chart.spin(2000, 0, 360); val l = chart!!.legend @@ -230,7 +230,7 @@ class PiePolylineChartActivity : DemoBase(), OnSeekBarChangeListener, OnChartVal } R.id.actionToggleSpin -> { - chart!!.spin(1000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.EaseInOutCubic) + chart!!.spin(1000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.easeInOutCubic) } R.id.actionSave -> { diff --git a/app/src/main/kotlin/info/appdev/chartexample/RadarChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/RadarChartActivity.kt index 34f3f8679a..9df9573bbb 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/RadarChartActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/RadarChartActivity.kt @@ -51,7 +51,7 @@ class RadarChartActivity : DemoBase() { setData() - chart!!.animateXY(1400, 1400, Easing.EaseInOutQuad) + chart!!.animateXY(1400, 1400, Easing.easeInOutQuad) val xAxis = chart!!.xAxis xAxis.typeface = tfLight @@ -219,7 +219,7 @@ class RadarChartActivity : DemoBase() { } R.id.actionToggleSpin -> { - chart!!.spin(2000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.EaseInOutCubic) + chart!!.spin(2000, chart!!.rotationAngle, chart!!.rotationAngle + 360, Easing.easeInOutCubic) } R.id.actionSave -> { diff --git a/app/src/main/kotlin/info/appdev/chartexample/SpecificPositionsLineChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/SpecificPositionsLineChartActivity.kt index 36c4d69d3e..c782fbed2a 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/SpecificPositionsLineChartActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/SpecificPositionsLineChartActivity.kt @@ -203,7 +203,7 @@ class SpecificPositionsLineChartActivity : DemoBase(), OnSeekBarChangeListener, } R.id.animateX -> mChart!!.animateX(3000) - R.id.animateY -> mChart!!.animateY(3000, Easing.EaseInCubic) + R.id.animateY -> mChart!!.animateY(3000, Easing.easeInCubic) R.id.animateXY -> mChart!!.animateXY(3000, 3000) R.id.actionSave -> { if (mChart!!.saveToPath("title" + System.currentTimeMillis(), "")) {