simetri.extensions.easing

  1#Penner's easing functions
  2# from https://github.com/semitable/easing-functions
  3
  4import math
  5
  6
  7class EasingBase:
  8    limit = (0, 1)
  9
 10    def __init__(self, start: float = 0, end: float = 1, duration: float = 1):
 11        self.start = start
 12        self.end = end
 13        self.duration = duration
 14
 15    def func(self, t: float) -> float:
 16        raise NotImplementedError
 17
 18    def ease(self, alpha: float) -> float:
 19        t = self.limit[0] * (1 - alpha) + self.limit[1] * alpha
 20        t /= self.duration
 21        a = self.func(t)
 22        return self.end * a + self.start * (1 - a)
 23
 24    def __call__(self, alpha: float) -> float:
 25        return self.ease(alpha)
 26
 27
 28"""
 29Linear
 30"""
 31class LinearInOut(EasingBase):
 32    def func(self, t: float) -> float:
 33        return t
 34
 35"""
 36Quadratic easing functions
 37"""
 38
 39
 40class QuadEaseInOut(EasingBase):
 41    def func(self, t: float) -> float:
 42        if t < 0.5:
 43            return 2 * t * t
 44        return (-2 * t * t) + (4 * t) - 1
 45
 46
 47class QuadEaseIn(EasingBase):
 48    def func(self, t: float) -> float:
 49        return t * t
 50
 51
 52class QuadEaseOut(EasingBase):
 53    def func(self, t: float) -> float:
 54        return -(t * (t - 2))
 55
 56
 57"""
 58Cubic easing functions
 59"""
 60
 61
 62class CubicEaseIn(EasingBase):
 63    def func(self, t: float) -> float:
 64        return t * t * t
 65
 66
 67class CubicEaseOut(EasingBase):
 68    def func(self, t: float) -> float:
 69        return (t - 1) * (t - 1) * (t - 1) + 1
 70
 71
 72class CubicEaseInOut(EasingBase):
 73    def func(self, t: float) -> float:
 74        if t < 0.5:
 75            return 4 * t * t * t
 76        p = 2 * t - 2
 77        return 0.5 * p * p * p + 1
 78
 79
 80"""
 81Quartic easing functions
 82"""
 83
 84
 85class QuarticEaseIn(EasingBase):
 86    def func(self, t: float) -> float:
 87        return t * t * t * t
 88
 89
 90class QuarticEaseOut(EasingBase):
 91    def func(self, t: float) -> float:
 92        return (t - 1) * (t - 1) * (t - 1) * (1 - t) + 1
 93
 94
 95class QuarticEaseInOut(EasingBase):
 96    def func(self, t: float) -> float:
 97        if t < 0.5:
 98            return 8 * t * t * t * t
 99        p = t - 1
100        return -8 * p * p * p * p + 1
101
102
103"""
104Quintic easing functions
105"""
106
107
108class QuinticEaseIn(EasingBase):
109    def func(self, t: float) -> float:
110        return t * t * t * t * t
111
112
113class QuinticEaseOut(EasingBase):
114    def func(self, t: float) -> float:
115        return (t - 1) * (t - 1) * (t - 1) * (t - 1) * (t - 1) + 1
116
117
118class QuinticEaseInOut(EasingBase):
119    def func(self, t: float) -> float:
120        if t < 0.5:
121            return 16 * t * t * t * t * t
122        p = (2 * t) - 2
123        return 0.5 * p * p * p * p * p + 1
124
125
126"""
127Sine easing functions
128"""
129
130
131class SineEaseIn(EasingBase):
132    def func(self, t: float) -> float:
133        return math.sin((t - 1) * math.pi / 2) + 1
134
135
136class SineEaseOut(EasingBase):
137    def func(self, t: float) -> float:
138        return math.sin(t * math.pi / 2)
139
140
141class SineEaseInOut(EasingBase):
142    def func(self, t: float) -> float:
143        return 0.5 * (1 - math.cos(t * math.pi))
144
145
146"""
147Circular easing functions
148"""
149
150
151class CircularEaseIn(EasingBase):
152    def func(self, t: float) -> float:
153        return 1 - math.sqrt(1 - (t * t))
154
155
156class CircularEaseOut(EasingBase):
157    def func(self, t: float) -> float:
158        return math.sqrt((2 - t) * t)
159
160
161class CircularEaseInOut(EasingBase):
162    def func(self, t: float) -> float:
163        if t < 0.5:
164            return 0.5 * (1 - math.sqrt(1 - 4 * (t * t)))
165        return 0.5 * (math.sqrt(-((2 * t) - 3) * ((2 * t) - 1)) + 1)
166
167
168"""
169Exponential easing functions
170"""
171
172
173class ExponentialEaseIn(EasingBase):
174    def func(self, t: float) -> float:
175        if t == 0:
176            return 0
177        return math.pow(2, 10 * (t - 1))
178
179
180class ExponentialEaseOut(EasingBase):
181    def func(self, t: float) -> float:
182        if t == 1:
183            return 1
184        return 1 - math.pow(2, -10 * t)
185
186
187class ExponentialEaseInOut(EasingBase):
188    def func(self, t: float) -> float:
189        if t == 0 or t == 1:
190            return t
191
192        if t < 0.5:
193            return 0.5 * math.pow(2, (20 * t) - 10)
194        return -0.5 * math.pow(2, (-20 * t) + 10) + 1
195
196
197"""
198Elastic Easing Functions
199"""
200
201
202class ElasticEaseIn(EasingBase):
203    def func(self, t: float) -> float:
204        return math.sin(13 * math.pi / 2 * t) * math.pow(2, 10 * (t - 1))
205
206
207class ElasticEaseOut(EasingBase):
208    def func(self, t: float) -> float:
209        return math.sin(-13 * math.pi / 2 * (t + 1)) * math.pow(2, -10 * t) + 1
210
211
212class ElasticEaseInOut(EasingBase):
213    def func(self, t: float) -> float:
214        if t < 0.5:
215            return (
216                0.5
217                * math.sin(13 * math.pi / 2 * (2 * t))
218                * math.pow(2, 10 * ((2 * t) - 1))
219            )
220        return 0.5 * (
221            math.sin(-13 * math.pi / 2 * ((2 * t - 1) + 1))
222            * math.pow(2, -10 * (2 * t - 1))
223            + 2
224        )
225
226
227"""
228Back Easing Functions
229"""
230
231
232class BackEaseIn(EasingBase):
233    def func(self, t: float) -> float:
234        return t * t * t - t * math.sin(t * math.pi)
235
236
237class BackEaseOut(EasingBase):
238    def func(self, t: float) -> float:
239        p = 1 - t
240        return 1 - (p * p * p - p * math.sin(p * math.pi))
241
242
243class BackEaseInOut(EasingBase):
244    def func(self, t: float) -> float:
245        if t < 0.5:
246            p = 2 * t
247            return 0.5 * (p * p * p - p * math.sin(p * math.pi))
248
249        p = 1 - (2 * t - 1)
250
251        return 0.5 * (1 - (p * p * p - p * math.sin(p * math.pi))) + 0.5
252
253
254"""
255Bounce Easing Functions
256"""
257
258
259class BounceEaseIn(EasingBase):
260    def func(self, t: float) -> float:
261        return 1 - BounceEaseOut().func(1 - t)
262
263
264class BounceEaseOut(EasingBase):
265    def func(self, t: float) -> float:
266        if t < 4 / 11:
267            return 121 * t * t / 16
268        elif t < 8 / 11:
269            return (363 / 40.0 * t * t) - (99 / 10.0 * t) + 17 / 5.0
270        elif t < 9 / 10:
271            return (4356 / 361.0 * t * t) - (35442 / 1805.0 * t) + 16061 / 1805.0
272        return (54 / 5.0 * t * t) - (513 / 25.0 * t) + 268 / 25.0
273
274
275class BounceEaseInOut(EasingBase):
276    def func(self, t: float) -> float:
277        if t < 0.5:
278            return 0.5 * BounceEaseIn().func(t * 2)
279        return 0.5 * BounceEaseOut().func(t * 2 - 1) + 0.5
280
281
282
283#####################################################################
284
285q = QuadEaseInOut(1, 0, 1)
286
287# for i in range(10):
288#     print(q(i/10))
289
290
291
292
293
294def cubicInterpolation(p0, p1, p2, p3, t):
295    t2 = t * t
296    t3 = t2 * t
297    return (
298        0.5
299        * (
300            (2 * p1)
301            + (-p0 + p2) * t
302            + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t2
303            + (-p0 + 3 * p1 - 3 * p2 + p3) * t3
304        )
305    )
306
307
308
309from numpy import array
310p1 = array([0, 0])
311p2 = array([1, 1])
312p3 = array([2, 1])
313p4 = array([3, 0])
314
315
316
317#print(cubicInterpolation(p1, p2, p3, p4, .5))
318
319
320def ease(alpha: float, duration=10, minV=0, maxV=1) -> float:
321    t = minV * (1 - alpha) + maxV * alpha
322    t /= duration
323    return t
324    # a = self.func(t)
325    # return self.end * a + self.start * (1 - a)
326
327
328#print(ease(1))
class EasingBase:
 8class EasingBase:
 9    limit = (0, 1)
10
11    def __init__(self, start: float = 0, end: float = 1, duration: float = 1):
12        self.start = start
13        self.end = end
14        self.duration = duration
15
16    def func(self, t: float) -> float:
17        raise NotImplementedError
18
19    def ease(self, alpha: float) -> float:
20        t = self.limit[0] * (1 - alpha) + self.limit[1] * alpha
21        t /= self.duration
22        a = self.func(t)
23        return self.end * a + self.start * (1 - a)
24
25    def __call__(self, alpha: float) -> float:
26        return self.ease(alpha)
EasingBase(start: float = 0, end: float = 1, duration: float = 1)
11    def __init__(self, start: float = 0, end: float = 1, duration: float = 1):
12        self.start = start
13        self.end = end
14        self.duration = duration
limit = (0, 1)
start
end
duration
def func(self, t: float) -> float:
16    def func(self, t: float) -> float:
17        raise NotImplementedError
def ease(self, alpha: float) -> float:
19    def ease(self, alpha: float) -> float:
20        t = self.limit[0] * (1 - alpha) + self.limit[1] * alpha
21        t /= self.duration
22        a = self.func(t)
23        return self.end * a + self.start * (1 - a)
class LinearInOut(EasingBase):
32class LinearInOut(EasingBase):
33    def func(self, t: float) -> float:
34        return t
def func(self, t: float) -> float:
33    def func(self, t: float) -> float:
34        return t
class QuadEaseInOut(EasingBase):
41class QuadEaseInOut(EasingBase):
42    def func(self, t: float) -> float:
43        if t < 0.5:
44            return 2 * t * t
45        return (-2 * t * t) + (4 * t) - 1
def func(self, t: float) -> float:
42    def func(self, t: float) -> float:
43        if t < 0.5:
44            return 2 * t * t
45        return (-2 * t * t) + (4 * t) - 1
class QuadEaseIn(EasingBase):
48class QuadEaseIn(EasingBase):
49    def func(self, t: float) -> float:
50        return t * t
def func(self, t: float) -> float:
49    def func(self, t: float) -> float:
50        return t * t
class QuadEaseOut(EasingBase):
53class QuadEaseOut(EasingBase):
54    def func(self, t: float) -> float:
55        return -(t * (t - 2))
def func(self, t: float) -> float:
54    def func(self, t: float) -> float:
55        return -(t * (t - 2))
class CubicEaseIn(EasingBase):
63class CubicEaseIn(EasingBase):
64    def func(self, t: float) -> float:
65        return t * t * t
def func(self, t: float) -> float:
64    def func(self, t: float) -> float:
65        return t * t * t
class CubicEaseOut(EasingBase):
68class CubicEaseOut(EasingBase):
69    def func(self, t: float) -> float:
70        return (t - 1) * (t - 1) * (t - 1) + 1
def func(self, t: float) -> float:
69    def func(self, t: float) -> float:
70        return (t - 1) * (t - 1) * (t - 1) + 1
class CubicEaseInOut(EasingBase):
73class CubicEaseInOut(EasingBase):
74    def func(self, t: float) -> float:
75        if t < 0.5:
76            return 4 * t * t * t
77        p = 2 * t - 2
78        return 0.5 * p * p * p + 1
def func(self, t: float) -> float:
74    def func(self, t: float) -> float:
75        if t < 0.5:
76            return 4 * t * t * t
77        p = 2 * t - 2
78        return 0.5 * p * p * p + 1
class QuarticEaseIn(EasingBase):
86class QuarticEaseIn(EasingBase):
87    def func(self, t: float) -> float:
88        return t * t * t * t
def func(self, t: float) -> float:
87    def func(self, t: float) -> float:
88        return t * t * t * t
class QuarticEaseOut(EasingBase):
91class QuarticEaseOut(EasingBase):
92    def func(self, t: float) -> float:
93        return (t - 1) * (t - 1) * (t - 1) * (1 - t) + 1
def func(self, t: float) -> float:
92    def func(self, t: float) -> float:
93        return (t - 1) * (t - 1) * (t - 1) * (1 - t) + 1
class QuarticEaseInOut(EasingBase):
 96class QuarticEaseInOut(EasingBase):
 97    def func(self, t: float) -> float:
 98        if t < 0.5:
 99            return 8 * t * t * t * t
100        p = t - 1
101        return -8 * p * p * p * p + 1
def func(self, t: float) -> float:
 97    def func(self, t: float) -> float:
 98        if t < 0.5:
 99            return 8 * t * t * t * t
100        p = t - 1
101        return -8 * p * p * p * p + 1
class QuinticEaseIn(EasingBase):
109class QuinticEaseIn(EasingBase):
110    def func(self, t: float) -> float:
111        return t * t * t * t * t
def func(self, t: float) -> float:
110    def func(self, t: float) -> float:
111        return t * t * t * t * t
class QuinticEaseOut(EasingBase):
114class QuinticEaseOut(EasingBase):
115    def func(self, t: float) -> float:
116        return (t - 1) * (t - 1) * (t - 1) * (t - 1) * (t - 1) + 1
def func(self, t: float) -> float:
115    def func(self, t: float) -> float:
116        return (t - 1) * (t - 1) * (t - 1) * (t - 1) * (t - 1) + 1
class QuinticEaseInOut(EasingBase):
119class QuinticEaseInOut(EasingBase):
120    def func(self, t: float) -> float:
121        if t < 0.5:
122            return 16 * t * t * t * t * t
123        p = (2 * t) - 2
124        return 0.5 * p * p * p * p * p + 1
def func(self, t: float) -> float:
120    def func(self, t: float) -> float:
121        if t < 0.5:
122            return 16 * t * t * t * t * t
123        p = (2 * t) - 2
124        return 0.5 * p * p * p * p * p + 1
class SineEaseIn(EasingBase):
132class SineEaseIn(EasingBase):
133    def func(self, t: float) -> float:
134        return math.sin((t - 1) * math.pi / 2) + 1
def func(self, t: float) -> float:
133    def func(self, t: float) -> float:
134        return math.sin((t - 1) * math.pi / 2) + 1
class SineEaseOut(EasingBase):
137class SineEaseOut(EasingBase):
138    def func(self, t: float) -> float:
139        return math.sin(t * math.pi / 2)
def func(self, t: float) -> float:
138    def func(self, t: float) -> float:
139        return math.sin(t * math.pi / 2)
class SineEaseInOut(EasingBase):
142class SineEaseInOut(EasingBase):
143    def func(self, t: float) -> float:
144        return 0.5 * (1 - math.cos(t * math.pi))
def func(self, t: float) -> float:
143    def func(self, t: float) -> float:
144        return 0.5 * (1 - math.cos(t * math.pi))
class CircularEaseIn(EasingBase):
152class CircularEaseIn(EasingBase):
153    def func(self, t: float) -> float:
154        return 1 - math.sqrt(1 - (t * t))
def func(self, t: float) -> float:
153    def func(self, t: float) -> float:
154        return 1 - math.sqrt(1 - (t * t))
class CircularEaseOut(EasingBase):
157class CircularEaseOut(EasingBase):
158    def func(self, t: float) -> float:
159        return math.sqrt((2 - t) * t)
def func(self, t: float) -> float:
158    def func(self, t: float) -> float:
159        return math.sqrt((2 - t) * t)
class CircularEaseInOut(EasingBase):
162class CircularEaseInOut(EasingBase):
163    def func(self, t: float) -> float:
164        if t < 0.5:
165            return 0.5 * (1 - math.sqrt(1 - 4 * (t * t)))
166        return 0.5 * (math.sqrt(-((2 * t) - 3) * ((2 * t) - 1)) + 1)
def func(self, t: float) -> float:
163    def func(self, t: float) -> float:
164        if t < 0.5:
165            return 0.5 * (1 - math.sqrt(1 - 4 * (t * t)))
166        return 0.5 * (math.sqrt(-((2 * t) - 3) * ((2 * t) - 1)) + 1)
class ExponentialEaseIn(EasingBase):
174class ExponentialEaseIn(EasingBase):
175    def func(self, t: float) -> float:
176        if t == 0:
177            return 0
178        return math.pow(2, 10 * (t - 1))
def func(self, t: float) -> float:
175    def func(self, t: float) -> float:
176        if t == 0:
177            return 0
178        return math.pow(2, 10 * (t - 1))
class ExponentialEaseOut(EasingBase):
181class ExponentialEaseOut(EasingBase):
182    def func(self, t: float) -> float:
183        if t == 1:
184            return 1
185        return 1 - math.pow(2, -10 * t)
def func(self, t: float) -> float:
182    def func(self, t: float) -> float:
183        if t == 1:
184            return 1
185        return 1 - math.pow(2, -10 * t)
class ExponentialEaseInOut(EasingBase):
188class ExponentialEaseInOut(EasingBase):
189    def func(self, t: float) -> float:
190        if t == 0 or t == 1:
191            return t
192
193        if t < 0.5:
194            return 0.5 * math.pow(2, (20 * t) - 10)
195        return -0.5 * math.pow(2, (-20 * t) + 10) + 1
def func(self, t: float) -> float:
189    def func(self, t: float) -> float:
190        if t == 0 or t == 1:
191            return t
192
193        if t < 0.5:
194            return 0.5 * math.pow(2, (20 * t) - 10)
195        return -0.5 * math.pow(2, (-20 * t) + 10) + 1
class ElasticEaseIn(EasingBase):
203class ElasticEaseIn(EasingBase):
204    def func(self, t: float) -> float:
205        return math.sin(13 * math.pi / 2 * t) * math.pow(2, 10 * (t - 1))
def func(self, t: float) -> float:
204    def func(self, t: float) -> float:
205        return math.sin(13 * math.pi / 2 * t) * math.pow(2, 10 * (t - 1))
class ElasticEaseOut(EasingBase):
208class ElasticEaseOut(EasingBase):
209    def func(self, t: float) -> float:
210        return math.sin(-13 * math.pi / 2 * (t + 1)) * math.pow(2, -10 * t) + 1
def func(self, t: float) -> float:
209    def func(self, t: float) -> float:
210        return math.sin(-13 * math.pi / 2 * (t + 1)) * math.pow(2, -10 * t) + 1
class ElasticEaseInOut(EasingBase):
213class ElasticEaseInOut(EasingBase):
214    def func(self, t: float) -> float:
215        if t < 0.5:
216            return (
217                0.5
218                * math.sin(13 * math.pi / 2 * (2 * t))
219                * math.pow(2, 10 * ((2 * t) - 1))
220            )
221        return 0.5 * (
222            math.sin(-13 * math.pi / 2 * ((2 * t - 1) + 1))
223            * math.pow(2, -10 * (2 * t - 1))
224            + 2
225        )
def func(self, t: float) -> float:
214    def func(self, t: float) -> float:
215        if t < 0.5:
216            return (
217                0.5
218                * math.sin(13 * math.pi / 2 * (2 * t))
219                * math.pow(2, 10 * ((2 * t) - 1))
220            )
221        return 0.5 * (
222            math.sin(-13 * math.pi / 2 * ((2 * t - 1) + 1))
223            * math.pow(2, -10 * (2 * t - 1))
224            + 2
225        )
class BackEaseIn(EasingBase):
233class BackEaseIn(EasingBase):
234    def func(self, t: float) -> float:
235        return t * t * t - t * math.sin(t * math.pi)
def func(self, t: float) -> float:
234    def func(self, t: float) -> float:
235        return t * t * t - t * math.sin(t * math.pi)
class BackEaseOut(EasingBase):
238class BackEaseOut(EasingBase):
239    def func(self, t: float) -> float:
240        p = 1 - t
241        return 1 - (p * p * p - p * math.sin(p * math.pi))
def func(self, t: float) -> float:
239    def func(self, t: float) -> float:
240        p = 1 - t
241        return 1 - (p * p * p - p * math.sin(p * math.pi))
class BackEaseInOut(EasingBase):
244class BackEaseInOut(EasingBase):
245    def func(self, t: float) -> float:
246        if t < 0.5:
247            p = 2 * t
248            return 0.5 * (p * p * p - p * math.sin(p * math.pi))
249
250        p = 1 - (2 * t - 1)
251
252        return 0.5 * (1 - (p * p * p - p * math.sin(p * math.pi))) + 0.5
def func(self, t: float) -> float:
245    def func(self, t: float) -> float:
246        if t < 0.5:
247            p = 2 * t
248            return 0.5 * (p * p * p - p * math.sin(p * math.pi))
249
250        p = 1 - (2 * t - 1)
251
252        return 0.5 * (1 - (p * p * p - p * math.sin(p * math.pi))) + 0.5
class BounceEaseIn(EasingBase):
260class BounceEaseIn(EasingBase):
261    def func(self, t: float) -> float:
262        return 1 - BounceEaseOut().func(1 - t)
def func(self, t: float) -> float:
261    def func(self, t: float) -> float:
262        return 1 - BounceEaseOut().func(1 - t)
class BounceEaseOut(EasingBase):
265class BounceEaseOut(EasingBase):
266    def func(self, t: float) -> float:
267        if t < 4 / 11:
268            return 121 * t * t / 16
269        elif t < 8 / 11:
270            return (363 / 40.0 * t * t) - (99 / 10.0 * t) + 17 / 5.0
271        elif t < 9 / 10:
272            return (4356 / 361.0 * t * t) - (35442 / 1805.0 * t) + 16061 / 1805.0
273        return (54 / 5.0 * t * t) - (513 / 25.0 * t) + 268 / 25.0
def func(self, t: float) -> float:
266    def func(self, t: float) -> float:
267        if t < 4 / 11:
268            return 121 * t * t / 16
269        elif t < 8 / 11:
270            return (363 / 40.0 * t * t) - (99 / 10.0 * t) + 17 / 5.0
271        elif t < 9 / 10:
272            return (4356 / 361.0 * t * t) - (35442 / 1805.0 * t) + 16061 / 1805.0
273        return (54 / 5.0 * t * t) - (513 / 25.0 * t) + 268 / 25.0
class BounceEaseInOut(EasingBase):
276class BounceEaseInOut(EasingBase):
277    def func(self, t: float) -> float:
278        if t < 0.5:
279            return 0.5 * BounceEaseIn().func(t * 2)
280        return 0.5 * BounceEaseOut().func(t * 2 - 1) + 0.5
def func(self, t: float) -> float:
277    def func(self, t: float) -> float:
278        if t < 0.5:
279            return 0.5 * BounceEaseIn().func(t * 2)
280        return 0.5 * BounceEaseOut().func(t * 2 - 1) + 0.5
q = <QuadEaseInOut object>
def cubicInterpolation(p0, p1, p2, p3, t):
295def cubicInterpolation(p0, p1, p2, p3, t):
296    t2 = t * t
297    t3 = t2 * t
298    return (
299        0.5
300        * (
301            (2 * p1)
302            + (-p0 + p2) * t
303            + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t2
304            + (-p0 + 3 * p1 - 3 * p2 + p3) * t3
305        )
306    )
p1 = array([0, 0])
p2 = array([1, 1])
p3 = array([2, 1])
p4 = array([3, 0])
def ease(alpha: float, duration=10, minV=0, maxV=1) -> float:
321def ease(alpha: float, duration=10, minV=0, maxV=1) -> float:
322    t = minV * (1 - alpha) + maxV * alpha
323    t /= duration
324    return t
325    # a = self.func(t)
326    # return self.end * a + self.start * (1 - a)