mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Move easing functions to separate file and add typing.
This commit is contained in:
@@ -2,13 +2,13 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
from math import pi, cos, sin, sqrt
|
||||
from time import time
|
||||
from tracemalloc import start
|
||||
from typing import Callable, TypeVar
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from ._easing import DEFAULT_EASING, EASING
|
||||
from ._timer import Timer
|
||||
from ._types import MessageTarget
|
||||
|
||||
@@ -28,133 +28,6 @@ class Animatable(Protocol):
|
||||
...
|
||||
|
||||
|
||||
def _in_out_expo(x):
|
||||
"""https://easings.net/#easeInOutExpo"""
|
||||
if 0 < x < 0.5:
|
||||
return pow(2, 20 * x - 10) / 2
|
||||
elif 0.5 <= x < 1:
|
||||
return (2 - pow(2, -20 * x + 10)) / 2
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _in_out_circ(x):
|
||||
"""https://easings.net/#easeInOutCirc"""
|
||||
if x < 0.5:
|
||||
return (1 - sqrt(1 - pow(2 * x, 2))) / 2
|
||||
else:
|
||||
return (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2
|
||||
|
||||
|
||||
def _in_out_back(x):
|
||||
"""https://easings.net/#easeInOutBack"""
|
||||
c = 1.70158 * 1.525
|
||||
if x < 0.5:
|
||||
return (pow(2 * x, 2) * ((c + 1) * 2 * x - c)) / 2
|
||||
else:
|
||||
return (pow(2 * x - 2, 2) * ((c + 1) * (x * 2 - 2) + c) + 2) / 2
|
||||
|
||||
|
||||
def _in_elastic(x):
|
||||
"""https://easings.net/#easeInElastic"""
|
||||
c = 2 * pi / 3;
|
||||
if 0 < x < 1:
|
||||
return -pow(2, 10 * x - 10) * sin((x * 10 - 10.75) * c)
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _in_out_elastic(x):
|
||||
"""https://easings.net/#easeInOutElastic"""
|
||||
c = 2 * pi / 4.5
|
||||
if 0 < x < 0.5:
|
||||
return -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c)) / 2
|
||||
elif 0.5 <= x < 1:
|
||||
return (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c)) / 2 + 1
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _out_elastic(x):
|
||||
"""https://easings.net/#easeInOutElastic"""
|
||||
c = 2 * pi / 4.5
|
||||
if 0 < x < 0.5:
|
||||
return -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c)) / 2
|
||||
elif 0.5 <= x < 1:
|
||||
return (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c)) / 2 + 1
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _out_bounce(x):
|
||||
"""https://easings.net/#easeOutBounce"""
|
||||
n, d = 7.5625, 2.75
|
||||
if x < 1/d:
|
||||
return n * x * x
|
||||
elif x < 2/d:
|
||||
x_ = x - 1.5/d
|
||||
return n * x_ * x_ + 0.75
|
||||
elif x < 2.5/d:
|
||||
x_ = x - 2.25/d
|
||||
return n * x_ * x_ + 0.9375
|
||||
else:
|
||||
x_ = x - 2.625/d
|
||||
return n * x_ * x_ + 0.984375
|
||||
|
||||
|
||||
def _in_bounce(x):
|
||||
"""https://easings.net/#easeInBounce"""
|
||||
return 1 - _out_bounce(x)
|
||||
|
||||
|
||||
def _in_out_bounce(x):
|
||||
"""https://easings.net/#easeInOutBounce"""
|
||||
if x < 0.5:
|
||||
return (1 - _out_bounce(1 - 2 * x)) / 2
|
||||
else:
|
||||
return (1 + _out_bounce(2 * x - 1)) / 2
|
||||
|
||||
|
||||
# https://easings.net/
|
||||
EASING = {
|
||||
"none": lambda x: 1.0,
|
||||
"round": lambda x: 0.0 if x < 0.5 else 1.0,
|
||||
"linear": lambda x: x,
|
||||
"in_sine": lambda x: 1 - cos((x * pi) / 2),
|
||||
"in_out_sine": lambda x: -(cos(x * pi) - 1) / 2,
|
||||
"out_sine": lambda x: sin((x * pi) / 2),
|
||||
"in_quad": lambda x: x * x,
|
||||
"in_out_quad": lambda x: 2 * x * x if x < 0.5 else 1 - pow(-2 * x + 2, 2) / 2,
|
||||
"out_quad": lambda x: 1 - pow(1 - x, 2),
|
||||
"in_cubic": lambda x: x * x * x,
|
||||
"in_out_cubic": lambda x: 4 * x * x * x if x < 0.5 else 1 - pow(-2 * x + 2, 3) / 2,
|
||||
"out_cubic": lambda x: 1 - pow(1 - x, 3),
|
||||
"in_quart": lambda x: pow(x, 4),
|
||||
"in_out_quart": lambda x: 8 * pow(x, 4) if x < 0.5 else 1 - pow(-2 * x + 2, 4) / 2,
|
||||
"out_quart": lambda x: 1 - pow(1 - x, 4),
|
||||
"in_quint": lambda x: pow(x, 5),
|
||||
"in_out_quint": lambda x: 16 * pow(x, 5) if x < 0.5 else 1 - pow(-2 * x + 2, 5) / 2,
|
||||
"out_quint": lambda x: 1 - pow(1 - x, 5),
|
||||
"in_expo": lambda x: pow(2, 10 * x - 10) if x else 0,
|
||||
"in_out_expo": _in_out_expo,
|
||||
"out_expo": lambda x: 1 - pow(2, -10 * x) if x != 1 else 1,
|
||||
"in_circ": lambda x: 1 - sqrt(1 - pow(x, 2)),
|
||||
"in_out_circ": _in_out_circ,
|
||||
"out_circ": lambda x: sqrt(1 - pow(x - 1, 2)),
|
||||
"in_back": lambda x: 2.70158 * pow(x, 3) - 1.70158 * pow(x, 2),
|
||||
"in_out_back": _in_out_back,
|
||||
"out_back": lambda x: 1 + 2.70158 * pow(x - 1, 3) + 1.70158 * pow(x - 1, 2),
|
||||
"in_elastic": _in_elastic,
|
||||
"in_out_elastic": _in_out_elastic,
|
||||
"out_elastic": _out_elastic,
|
||||
"in_bounce": _in_bounce,
|
||||
"in_out_bounce": _in_out_bounce,
|
||||
"out_bounce": _out_bounce,
|
||||
}
|
||||
|
||||
DEFAULT_EASING = "in_out_cubic"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Animation:
|
||||
obj: object
|
||||
|
||||
132
src/textual/_easing.py
Normal file
132
src/textual/_easing.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
Define a series of easing functions for more natural-looking animations.
|
||||
Taken from https://easings.net/ and translated from JavaScript.
|
||||
"""
|
||||
|
||||
from math import pi, cos, sin, sqrt
|
||||
|
||||
|
||||
def _in_out_expo(x: float) -> float:
|
||||
"""https://easings.net/#easeInOutExpo"""
|
||||
if 0 < x < 0.5:
|
||||
return pow(2, 20 * x - 10) / 2
|
||||
elif 0.5 <= x < 1:
|
||||
return (2 - pow(2, -20 * x + 10)) / 2
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _in_out_circ(x: float) -> float:
|
||||
"""https://easings.net/#easeInOutCirc"""
|
||||
if x < 0.5:
|
||||
return (1 - sqrt(1 - pow(2 * x, 2))) / 2
|
||||
else:
|
||||
return (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2
|
||||
|
||||
|
||||
def _in_out_back(x: float) -> float:
|
||||
"""https://easings.net/#easeInOutBack"""
|
||||
c = 1.70158 * 1.525
|
||||
if x < 0.5:
|
||||
return (pow(2 * x, 2) * ((c + 1) * 2 * x - c)) / 2
|
||||
else:
|
||||
return (pow(2 * x - 2, 2) * ((c + 1) * (x * 2 - 2) + c) + 2) / 2
|
||||
|
||||
|
||||
def _in_elastic(x: float) -> float:
|
||||
"""https://easings.net/#easeInElastic"""
|
||||
c = 2 * pi / 3
|
||||
if 0 < x < 1:
|
||||
return -pow(2, 10 * x - 10) * sin((x * 10 - 10.75) * c)
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _in_out_elastic(x: float) -> float:
|
||||
"""https://easings.net/#easeInOutElastic"""
|
||||
c = 2 * pi / 4.5
|
||||
if 0 < x < 0.5:
|
||||
return -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c)) / 2
|
||||
elif 0.5 <= x < 1:
|
||||
return (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c)) / 2 + 1
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _out_elastic(x: float) -> float:
|
||||
"""https://easings.net/#easeInOutElastic"""
|
||||
c = 2 * pi / 4.5
|
||||
if 0 < x < 0.5:
|
||||
return -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c)) / 2
|
||||
elif 0.5 <= x < 1:
|
||||
return (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c)) / 2 + 1
|
||||
else:
|
||||
return x # x in (0, 1)
|
||||
|
||||
|
||||
def _out_bounce(x: float) -> float:
|
||||
"""https://easings.net/#easeOutBounce"""
|
||||
n, d = 7.5625, 2.75
|
||||
if x < 1 / d:
|
||||
return n * x * x
|
||||
elif x < 2 / d:
|
||||
x_ = x - 1.5 / d
|
||||
return n * x_ * x_ + 0.75
|
||||
elif x < 2.5 / d:
|
||||
x_ = x - 2.25 / d
|
||||
return n * x_ * x_ + 0.9375
|
||||
else:
|
||||
x_ = x - 2.625 / d
|
||||
return n * x_ * x_ + 0.984375
|
||||
|
||||
|
||||
def _in_bounce(x: float) -> float:
|
||||
"""https://easings.net/#easeInBounce"""
|
||||
return 1 - _out_bounce(x)
|
||||
|
||||
|
||||
def _in_out_bounce(x: float) -> float:
|
||||
"""https://easings.net/#easeInOutBounce"""
|
||||
if x < 0.5:
|
||||
return (1 - _out_bounce(1 - 2 * x)) / 2
|
||||
else:
|
||||
return (1 + _out_bounce(2 * x - 1)) / 2
|
||||
|
||||
|
||||
EASING = {
|
||||
"none": lambda x: 1.0,
|
||||
"round": lambda x: 0.0 if x < 0.5 else 1.0,
|
||||
"linear": lambda x: x,
|
||||
"in_sine": lambda x: 1 - cos((x * pi) / 2),
|
||||
"in_out_sine": lambda x: -(cos(x * pi) - 1) / 2,
|
||||
"out_sine": lambda x: sin((x * pi) / 2),
|
||||
"in_quad": lambda x: x * x,
|
||||
"in_out_quad": lambda x: 2 * x * x if x < 0.5 else 1 - pow(-2 * x + 2, 2) / 2,
|
||||
"out_quad": lambda x: 1 - pow(1 - x, 2),
|
||||
"in_cubic": lambda x: x * x * x,
|
||||
"in_out_cubic": lambda x: 4 * x * x * x if x < 0.5 else 1 - pow(-2 * x + 2, 3) / 2,
|
||||
"out_cubic": lambda x: 1 - pow(1 - x, 3),
|
||||
"in_quart": lambda x: pow(x, 4),
|
||||
"in_out_quart": lambda x: 8 * pow(x, 4) if x < 0.5 else 1 - pow(-2 * x + 2, 4) / 2,
|
||||
"out_quart": lambda x: 1 - pow(1 - x, 4),
|
||||
"in_quint": lambda x: pow(x, 5),
|
||||
"in_out_quint": lambda x: 16 * pow(x, 5) if x < 0.5 else 1 - pow(-2 * x + 2, 5) / 2,
|
||||
"out_quint": lambda x: 1 - pow(1 - x, 5),
|
||||
"in_expo": lambda x: pow(2, 10 * x - 10) if x else 0,
|
||||
"in_out_expo": _in_out_expo,
|
||||
"out_expo": lambda x: 1 - pow(2, -10 * x) if x != 1 else 1,
|
||||
"in_circ": lambda x: 1 - sqrt(1 - pow(x, 2)),
|
||||
"in_out_circ": _in_out_circ,
|
||||
"out_circ": lambda x: sqrt(1 - pow(x - 1, 2)),
|
||||
"in_back": lambda x: 2.70158 * pow(x, 3) - 1.70158 * pow(x, 2),
|
||||
"in_out_back": _in_out_back,
|
||||
"out_back": lambda x: 1 + 2.70158 * pow(x - 1, 3) + 1.70158 * pow(x - 1, 2),
|
||||
"in_elastic": _in_elastic,
|
||||
"in_out_elastic": _in_out_elastic,
|
||||
"out_elastic": _out_elastic,
|
||||
"in_bounce": _in_bounce,
|
||||
"in_out_bounce": _in_out_bounce,
|
||||
"out_bounce": _out_bounce,
|
||||
}
|
||||
|
||||
DEFAULT_EASING = "in_out_cubic"
|
||||
Reference in New Issue
Block a user