Processingによるイージング

Processingでイージングを簡単に使えるものを作ったので紹介します。

参考サイト
* イージングチートシート: https://easings.net/ja#easeInOutElastic
* ヘロンの数学チャンネル: https://www.youtube.com/watch?v=I6GxFRtZcNE

### 使い方
1. Processing内で新しいタブを選び、一番下のコードをコピペする
2. easingFrameRateを更新する（通常は60)
3. Easingクラスを定義する
```easing.pdf
Easing hoge;
```
4. 定義したEasingクラスを初期化する
``` easing.pdf
hoge = new Easing("イージングの種類", イージング時間[s]);
```
5. draw関数内でhoge.update()で更新し、０～１の更新された値を取得する
```
void draw(){
    float eased_value = hoge.update();
}
```

### Sample Code

```sample.pde
// easingの初期化
int easingFrameRate = 60;
int waitingTime = 2;
Easing easeX = new Easing("easeInOut", waitingTime);
Easing easeY = new Easing("linear", waitingTime);

void setup() {
  size(500, 500);
  frameRate(60);
}

void draw() {
  background(255);

  stroke(2);
  noFill();
  rect(100, 100, 300, 300);

  noStroke();
  fill(#6A90E0);
  float eased_x = easeX.update();
  float eased_y = easeY.update();

  // 0 ~ 1の値を0 ~ 300の値に拡大する。
  ellipse(eased_x * 300 + 100, eased_y * 300 + 100, 20, 20);
}

```
下記のGifのようなものを出力します。

### イージングの種類
<img width="300" alt="" src="">

linear
<img width="300" alt="linear.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/3daeafc0-e1b6-54e3-83ad-ee65c550acef.gif">

easeIn
<img width="300" alt="easeIn.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/892c8387-622a-4c55-397c-2427f04f01f9.gif">

easeInBack
<img width="300" alt="easeInBack.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/a9c5ae8a-6867-fea8-0930-bd1471c62112.gif">

easeInCirc
<img width="300" alt="easeInCirc.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/9cb8889c-6e0a-1899-1108-3e7e86c76878.gif">

easeInElastic
<img width="300" alt="easeInElastic.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/07c96a85-235c-349a-100e-f222cdae787b.gif">

easeInOut
<img width="300" alt="easeInOut.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/bd5a94db-86b5-1c5b-99cb-8afc43ea8537.gif">

easeInOutBack
<img width="300" alt="easeInOutBack.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/d9755108-3030-54a4-2a38-f243c0bd42f1.gif">

easeInOutCirc
<img width="300" alt="easeInOutCirc.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/b9bd8f01-11b8-a15f-b02d-b2f119aba7f5.gif">

easeInOutElastic
<img width="300" alt="easeInOutElastic.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/f77870fd-5454-7965-935b-4e5732efcaa4.gif">

easeOut
<img width="300" alt="easeOut.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/73577578-56f0-135f-1279-96bfe2ffefac.gif">

easeOutBack
<img width="300" alt="easeOutBack.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/8567e67a-f747-dc5f-6027-d1b30fec8200.gif">

easeOutCirc
<img width="300" alt="easeOutCirc.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/b4c2d8f3-5dcb-9c91-08c1-bb4a7514202a.gif">

easeOutElastic
<img width="300" alt="easeOutElastic" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3737296/8afd7808-d5da-e138-39fb-ef18fc19fea2.gif">

### Code

```
class Easing {
  String type;
  float period;
  float time;
  Easing(String type, float period) {
    this.type = type;
    this.period = period * easingFrameRate;
    this.time = 0;
  }

  // time ease in 0 to 1
  // A larger time include returning value

  Float update() {
    Float result = null;

    if (type == "linear") result = linearEase();
    if (type == "easeIn") result = easeIn();
    if (type == "easeOut") result = easeOut();
    if (type == "easeInOut") result = easeInOut();
    if (type == "easeInCirc") result = easeInCirc();
    if (type == "easeOutCirc") result = easeOutCirc();
    if (type == "easeInOutCirc") result = easeInOutCirc();
    if (type == "easeInBack") result = easeInBack();
    if (type == "easeOutBack") result = easeOutBack();
    if (type == "easeInOutBack") result = easeInOutBack();
    if (type == "easeInElastic") result = easeInElastic();
    if (type == "easeOutElastic") result = easeOutElastic();
    if (type == "easeInOutElastic") result = easeInOutElastic();

    time++;

    if (result == null) {
      throw new RuntimeException("イージング名が無効です");
    }
    return result;
  }

  Float linearEase() {
    if (time > period) return 1.;
    return map(time, 0, period, 0, 1);
  }

  Float easeIn() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    float y = x*x;
    return y;
  }

  Float easeOut() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    float y = -(x*x) + 2*x;
    return y;
  }

  Float easeInOut() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    Float y = null;
    if (time <= period / 2) y = 2 * x*x;
    if (time > period / 2) y = -2 * (x-1)*(x-1) + 1;
    return y;
  }

  Float easeInCirc() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    float y = 1 - sqrt(1 - x * x);
    return y;
  }

  Float easeOutCirc() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    float y = sqrt(1 - (x-1)*(x-1));
    return y;
  }

  Float easeInOutCirc() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    Float y = null;
    if (time <= period / 2) y = (1 - sqrt(1 - (2*x)*(2*x))) / 2;
    if (time > period / 2) y = (sqrt(1 - (-2*x+2)*(-2*x+2)) + 1) / 2;
    return y;
  }

  Float easeInBack() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    final float c1 = 1.70158; // magic number!
    final float c3 = c1 + 1;
    float y = c3 * x*x*x - c1 *x*x;
    return y;
  }

  Float easeOutBack() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    final float c1 = 1.70158; // magic number!
    final float c3 = c1 + 1;
    float y = 1 + c3 * (x-1)*(x-1)*(x-1) + c1 * (x-1)*(x-1);
    return y;
  }

  Float easeInOutBack() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    final float c1 = 1.70158; // magic number!
    final float c2 = c1 * 1.525; // again magic!
    Float y = null;
    if (time <= period / 2)  y = ((2*x)*(2*x) * ((c2+1)*2*x -c2)) / 2;
    if (time > period / 2) y = ((2*x-2)*(2*x-2) * ((c2+1) * (x*2-2) + c2) + 2) / 2;
    return y;
  }

  Float easeInElastic() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    final float c4 = (2. * PI) / 3.;
    if (x == 0) return 0.;
    if (x == 1) return 1.;
    float y = -pow(2, 10*x - 10) * sin((x*10 - 10.75) * c4);
    return y;
  }

  Float easeOutElastic() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    final float c4 = (2 * PI) / 3;
    if (x == 0) return 0.;
    if (x == 1) return 1.;
    float y = pow(2, -10*x) * sin((x*10 - 0.75) * c4) + 1;
    return y;
  }

  Float easeInOutElastic() {
    if (time > period) return 1.;
    float x = map(time, 0, period, 0, 1);
    final float c5 = (2 * PI) / 4.5;
    if (x == 0) return 0.;
    if (x == 1) return 1.;
    Float y = null;
    if (time <= period / 2) y = -(pow(2, 20*x - 10) * sin((20*x - 11.125) * c5)) / 2;
    if (time > period / 2) y = (pow(2, -20*x + 10) * sin((20*x - 11.125) * c5)) / 2 + 1;
    return y;
  }
}
```