You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Kivy中Line组件circle参数的半径平滑动画效果?

问题描述

我的预期效果:
将半径为100px的圆形通过动画过渡到半径150px的状态,我认为解决方案应该比较简单,但目前我没有找到可行的实现方法。

最小可复现代码

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Line, Ellipse
from kivy.clock import Clock
from kivy.animation import Animation


class AnimationExample(BoxLayout):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        Clock.schedule_interval(self.animate, 2)

        with self.canvas:
            self.pulsating_line = Line(
                        circle=(self.center_x, self.center_y, 100),
                        width=2)

        self.bind(size = self.update,
                    pos = self.update
                    )

    def update(self, *args):
        self.pulsating_line.circle = (self.center_x,
                                      self.center_y,
                                      100,
                                      )
    def animate(self, *args):
        print('Animate')

        circ = self.pulsating_line
        circ.circle = (self.center_x,
                       self.center_y,
                       100,
                       )
        circ.width = 2

        # This works for animated "width"
        Animation(width=8,
            t='out_bounce',
            d=1.1).start(circ)
   
        # In my opinion is this analogical approach, but of course, it not works :/
        # Animation(circle=(self.center_x,
        #                   self.center_y,
        #                   150,
        #                   ),
        #           t='out_bounce',
        #           d=0.8).start(circ)

class TutorialApp(App):
    def build(self):
        return AnimationExample()

TutorialApp().run()
解决方法

你不能直接对Line.circle元组属性做过渡动画,Kivy的Animation默认不支持元组类型的属性差值计算。可以通过自定义可动画的数值属性实现需求,修改后的代码如下:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Line
from kivy.clock import Clock
from kivy.animation import Animation
from kivy.properties import NumericProperty


class AnimationExample(BoxLayout):
    # 自定义圆形半径属性,支持动画过渡
    circle_r = NumericProperty(100)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        Clock.schedule_interval(self.animate, 2)

        with self.canvas:
            self.pulsating_line = Line(
                        circle=(self.center_x, self.center_y, self.circle_r),
                        width=2)
        
        # 绑定属性变化事件:位置/尺寸改变、半径改变时都更新圆形
        self.bind(size = self.update_circle,
                  pos = self.update_circle,
                  circle_r = self.update_circle
                  )

    def update_circle(self, *args):
        self.pulsating_line.circle = (self.center_x,
                                      self.center_y,
                                      self.circle_r,
                                      )
    def animate(self, *args):
        print('Animate')

        circ = self.pulsating_line
        # 重置初始状态
        self.circle_r = 100
        circ.width = 2

        # 原有描边宽度动画保留
        Animation(width=8,
            t='out_bounce',
            d=1.1).start(circ)
   
        # 直接动画自定义的半径属性即可
        Animation(circle_r=150,
                  t='out_bounce',
                  d=0.8).start(self)

class TutorialApp(App):
    def build(self):
        return AnimationExample()

TutorialApp().run()

修改逻辑说明:

  • 新增NumericProperty类型的circle_r属性存储圆形半径,Kivy的Animation原生支持数值类型属性的过渡计算
  • 绑定circle_r属性的变化事件,属性更新时自动刷新圆形的半径参数
  • 动画逻辑改为直接对circle_r属性做过渡,即可实现圆形半径从100px到150px的平滑动画效果

内容的提问来源于stack exchange,提问作者lukassliacky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:24:01