github.com/acrespo/mobile@v0.0.0-20190107162257-dc0771356504/exp/sprite/clock/tween.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package clock
     6  
     7  // Standard tween functions.
     8  //
     9  // Easing means a slowing near the timing boundary, as defined by
    10  // a cubic bezier curve. Exact parameters match the CSS properties.
    11  var (
    12  	EaseIn    = CubicBezier(0.42, 0, 1, 1)
    13  	EaseOut   = CubicBezier(0, 0, 0.58, 1)
    14  	EaseInOut = CubicBezier(0.42, 0, 0.58, 1)
    15  )
    16  
    17  // Linear computes the fraction [0,1] that t lies between [t0,t1].
    18  func Linear(t0, t1, t Time) float32 {
    19  	if t >= t1 {
    20  		return 1
    21  	}
    22  	if t <= t0 {
    23  		return 0
    24  	}
    25  	return float32(t-t0) / float32(t1-t0)
    26  }
    27  
    28  // CubicBezier generates a tween function determined by a Cubic Bézier curve.
    29  //
    30  // The parameters are cubic control parameters. The curve starts at (0,0)
    31  // going toward (x0,y0), and arrives at (1,1) coming from (x1,y1).
    32  func CubicBezier(x0, y0, x1, y1 float32) func(t0, t1, t Time) float32 {
    33  	return func(start, end, now Time) float32 {
    34  		// A Cubic-Bezier curve restricted to starting at (0,0) and
    35  		// ending at (1,1) is defined as
    36  		//
    37  		// 	B(t) = 3*(1-t)^2*t*P0 + 3*(1-t)*t^2*P1 + t^3
    38  		//
    39  		// with derivative
    40  		//
    41  		//	B'(t) = 3*(1-t)^2*P0 + 6*(1-t)*t*(P1-P0) + 3*t^2*(1-P1)
    42  		//
    43  		// Given a value x ∈ [0,1], we solve for t using Newton's
    44  		// method and solve for y using t.
    45  
    46  		x := Linear(start, end, now)
    47  
    48  		// Solve for t using x.
    49  		t := x
    50  		for i := 0; i < 5; i++ {
    51  			t2 := t * t
    52  			t3 := t2 * t
    53  			d := 1 - t
    54  			d2 := d * d
    55  
    56  			nx := 3*d2*t*x0 + 3*d*t2*x1 + t3
    57  			dxdt := 3*d2*x0 + 6*d*t*(x1-x0) + 3*t2*(1-x1)
    58  			if dxdt == 0 {
    59  				break
    60  			}
    61  
    62  			t -= (nx - x) / dxdt
    63  			if t <= 0 || t >= 1 {
    64  				break
    65  			}
    66  		}
    67  		if t < 0 {
    68  			t = 0
    69  		}
    70  		if t > 1 {
    71  			t = 1
    72  		}
    73  
    74  		// Solve for y using t.
    75  		t2 := t * t
    76  		t3 := t2 * t
    77  		d := 1 - t
    78  		d2 := d * d
    79  		y := 3*d2*t*y0 + 3*d*t2*y1 + t3
    80  
    81  		return y
    82  	}
    83  }