76 lines
2.2 KiB
Python
76 lines
2.2 KiB
Python
__all__ = ('interpolate', 'fade_transition', )
|
|
import typing as T
|
|
from contextlib import asynccontextmanager
|
|
from kivy.animation import AnimationTransition
|
|
|
|
from ._anim_with_xxx import anim_with_ratio
|
|
|
|
|
|
linear = AnimationTransition.linear
|
|
|
|
|
|
async def interpolate(start, end, *, duration=1.0, step=0, transition=linear) -> T.AsyncIterator:
|
|
'''
|
|
Interpolates between the values ``start`` and ``end`` in an async-manner.
|
|
Inspired by wasabi2d's interpolate_.
|
|
|
|
.. code-block::
|
|
|
|
async for v in interpolate(0, 100, duration=1.0, step=.3):
|
|
print(int(v))
|
|
|
|
============ ======
|
|
elapsed time output
|
|
============ ======
|
|
0 sec 0
|
|
0.3 sec 30
|
|
0.6 sec 60
|
|
0.9 sec 90
|
|
**1.2 sec** 100
|
|
============ ======
|
|
|
|
.. _interpolate: https://wasabi2d.readthedocs.io/en/stable/coros.html#clock.coro.interpolate
|
|
'''
|
|
if isinstance(transition, str):
|
|
transition = getattr(AnimationTransition, transition)
|
|
|
|
slope = end - start
|
|
yield transition(0.) * slope + start
|
|
async for p in anim_with_ratio(step=step, duration=duration):
|
|
if p >= 1.0:
|
|
break
|
|
yield transition(p) * slope + start
|
|
yield transition(1.) * slope + start
|
|
|
|
|
|
@asynccontextmanager
|
|
async def fade_transition(*widgets, duration=1.0, step=0) -> T.AsyncContextManager:
|
|
'''
|
|
Returns an async context manager that:
|
|
|
|
* fades-out the given widgets on ``__aenter__``.
|
|
* fades-in the given widgets on ``__aexit__``.
|
|
|
|
.. code-block::
|
|
|
|
async with fade_transition(widget1, widget2):
|
|
...
|
|
|
|
The ``widgets`` don't have to be actual Kivy widgets.
|
|
Anything that has an attribute named ``opacity`` would work.
|
|
'''
|
|
half_duration = duration / 2.
|
|
org_opas = tuple(w.opacity for w in widgets)
|
|
try:
|
|
async for p in anim_with_ratio(duration=half_duration, step=step):
|
|
p = 1.0 - p
|
|
for w, o in zip(widgets, org_opas):
|
|
w.opacity = p * o
|
|
yield
|
|
async for p in anim_with_ratio(duration=half_duration, step=step):
|
|
for w, o in zip(widgets, org_opas):
|
|
w.opacity = p * o
|
|
finally:
|
|
for w, o in zip(widgets, org_opas):
|
|
w.opacity = o
|