Kivy Line(circle=(x, y, r)) - radius 动画

Kivy Line(circle=(x, y, r)) - radius Animation

我的期望:

半径为 100 像素的圆将被动画化为半径为 150 像素。解决方案可能很简单,但这个问题不在我的知识范围内...

最小示例

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()

动画 canvas 指令的一种便捷方法是使用 Propertieskvkv 自动设置 Properties 的绑定,因此动画只是为那些 Properties 设置动画。这是使用该方法的代码的修改版本:

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import NumericProperty, ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.animation import Animation

kv = '''
<AnimationExample>:
    canvas:
        Color:
            rgba: self.circle_color
        Line:
            circle: self.center_x, self.center_y, self.radius  # this sets up bindings to the Properties defined in AnimationExample
            width: self.line_width  # this sets up a binding to the line_width Property
        
'''


class AnimationExample(BoxLayout):
    # define properties for the circle
    circle_color = ListProperty([1, 0, 0, 1])
    radius = NumericProperty(100)
    line_width = NumericProperty(2)

    def animate(self, *args):
        # since the kv sets up bindings to the properties of this class, we can just animate those properties
        print('Animate')

        # This works for animated "width"
        width_anim = Animation(line_width=8, t='out_bounce', d=1) + Animation(line_width=2, t='out_bounce', d=1)
        width_anim.start(self)

        # to animate the circle radius
        radius_anim = Animation(radius=150, d=1) + Animation(radius=100, d=1)
        radius_anim.start(self)


class TutorialApp(App):
    def build(self):
        Builder.load_string(kv)
        r = AnimationExample()
        Clock.schedule_interval(r.animate, 2)
        return r


TutorialApp().run()