From bc6975d81ef1d647ce32d3b74a50fef2e890d208 Mon Sep 17 00:00:00 2001 From: Nattosai Mito Date: Wed, 12 Aug 2026 18:45:22 +0900 Subject: [PATCH 1/2] Transition: Make `iris` support widget as target --- examples/transition_showcase.py | 8 ++++---- src/asynckivy/transition.py | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/examples/transition_showcase.py b/examples/transition_showcase.py index 35a23e3..3c19b2e 100644 --- a/examples/transition_showcase.py +++ b/examples/transition_showcase.py @@ -45,19 +45,19 @@ async def main(self): async with t.gl_transitions_dot_com(label, fs=cross_warp): label.text = 'iris' - await touch_down() - async with t.iris(duration=0.8, color=colormap['darkslategray']): + __, touch = await touch_down() + async with t.iris(color=colormap["darkslategray"], circle_center=touch.pos): label.halign = 'center' label.text = 'iris with a custom overlay' - await touch_down() + __, touch = await touch_down() rect = Rectangle(size=Window.size, source='data/logo/kivy-icon-128.png') texture = rect.texture texture.wrap = 'repeat' x_ratio = Window.width / texture.width y_ratio = Window.height / texture.height rect.tex_coords = (0, y_ratio, x_ratio, y_ratio, x_ratio, 0, 0, 0) - async with t.iris(overlay=rect, out_curve='linear', in_curve='linear'): + async with t.iris(overlay=rect, out_curve="linear", in_curve="linear", circle_center=touch.pos): await ak.sleep(.3) label.text = 'slide' await ak.sleep(.3) diff --git a/src/asynckivy/transition.py b/src/asynckivy/transition.py index d312f7f..1b19116 100644 --- a/src/asynckivy/transition.py +++ b/src/asynckivy/transition.py @@ -131,38 +131,41 @@ async def scale(target: Wow=Window, *, duration=1, out_curve='out_quad', in_curv await anim_attrs(mat, d=half_d, t=in_curve, xyz=(1, 1, 1)) -def _calc_enclosing_circle_radius(circle_center, rectangle_size, max=max, hypot=math.hypot, abs=abs): +def _calc_enclosing_circle_radius(circle_center, rect_pos, rect_size, max=max, hypot=math.hypot, abs=abs): ''' Calculates the minimum radius required for a circle centered at the given position to fully - enclose a rectangle of the given size, assuming its bottom-left corner is at (0, 0). + enclose the rectangle defined by the given position and size. .. code-block:: - radius = _calc_enclosing_circle_radius(circle_center, rectangle_size) + radius = _calc_enclosing_circle_radius(circle_center, widget.pos, widget.size) ''' - w, h = rectangle_size - x, y = circle_center - return hypot(max(abs(x), abs(w - x)), max(abs(y), abs(h - y))) + cx, cy = circle_center + rx, ry = rect_pos + rw, rh = rect_size + return hypot(max(abs(cx - rx), abs(rx + rw - cx)), max(abs(cy - ry), abs(ry + rh - cy))) @asynccontextmanager -async def iris(target: WindowBase=Window, *, duration=1, out_curve='in_cubic', in_curve='out_cubic', +async def iris(target: Wow=Window, *, duration=1, out_curve='in_cubic', in_curve='out_cubic', color: Sequence[float]=colormap['white'], circle_center: Sequence[float]=None, overlay: VertexInstruction=None): ''' - 縮む円によって ``target`` が見える範囲を絞っていき、完全に見えなくなったらwithブロック内を実行し、その後円を広げて ``target`` を再び見せる。 + Narrows the visible area of ``target`` with a shrinking circle, runs the code inside the with-block + once it becomes completely invisible, and then expands the circle to make ``target`` visible again. .. versionadded:: 0.9.0 + .. versionchanged:: 0.11.1 + Added support for widget as target. ''' - if not isinstance(target, WindowBase): - raise TypeError(f"'target' must be a WindowBase instance, not {type(target).__name__}") half_d = duration / 2 canvas = target.canvas if circle_center is None: circle_center = target.center if overlay is None: overlay = Rectangle(size=target.size) - radius = _calc_enclosing_circle_radius(circle_center, target.size) + target_pos = (0, 0) if isinstance(target, WindowBase) else target.pos + radius = _calc_enclosing_circle_radius(circle_center, target_pos, target.size) diameter = radius * 2. ellipse_start_pos = (circle_center[0] - radius, circle_center[1] - radius) ellipse_start_size = (diameter, diameter) From fdc041e5454d2f0d3b880ff4ffa557b484b52743 Mon Sep 17 00:00:00 2001 From: Nattosai Mito Date: Thu, 13 Aug 2026 06:12:09 +0900 Subject: [PATCH 2/2] =?UTF-8?q?`target`=20=E3=81=8Crelative=E7=B3=BB?= =?UTF-8?q?=E3=81=A7=E3=81=82=E3=82=8B=E5=A0=B4=E5=90=88=E3=81=AB=E5=82=99?= =?UTF-8?q?=E3=81=88=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/asynckivy/transition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/asynckivy/transition.py b/src/asynckivy/transition.py index 1b19116..20f9b6d 100644 --- a/src/asynckivy/transition.py +++ b/src/asynckivy/transition.py @@ -183,7 +183,7 @@ async def iris(target: Wow=Window, *, duration=1, out_curve='in_cubic', in_curve ig_add(inner_ig) ig_add(StencilPop()) - canvas.add(ig) + canvas.after.add(ig) try: await anim_attrs(ellipse, d=half_d, t=out_curve, pos=circle_center, size=(0, 0)) # Setting the ellipse size to (0, 0) isn't enough to nullify the stencil effect for some reason, @@ -193,7 +193,7 @@ async def iris(target: Wow=Window, *, duration=1, out_curve='in_cubic', in_curve inner_ig.add(ellipse) await anim_attrs(ellipse, d=half_d, t=in_curve, pos=ellipse_start_pos, size=ellipse_start_size) finally: - canvas.remove(ig) + canvas.after.remove(ig) @asynccontextmanager