如何在动画过程中保持圆居中

问题描述 投票:0回答:1

大家好,我正在使用 python kivy 应用程序开发 Chwazi 小丑。 快速背景:在这个应用程序中,当您按下(并按住并跳动(变大变小))时会出现一个圆圈 我遇到了跳动动画的问题,因为当我使用这个功能时:

def beat_animation(self, circle):
        anim = Animation(size=(circle.size[0]*1.2, circle.size[1]*1.2), duration=0.5)
        anim += Animation(size=(circle.size[0], circle.size[1]), duration=0.5)
        anim.repeat = True
        anim.start(circle)

我的圆圈按照我想要的那样越来越大越来越小,但问题是它没有保持在光标周围。 (这是一个应用程序,它支持多点触控,所以它应该对所有圈子都这样做)

这是完整的代码:

import random

import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Ellipse, Color
from kivy.uix.label import Label
from kivy.animation import Animation


class Touch(Widget):
    def __init__(self, **kwargs):
        super(Touch, self).__init__(**kwargs)
        self.circles = {}  # Dictionary to store circles for each finger

    def on_touch_down(self, touch):
        if touch.id not in self.circles:
            with self.canvas:
                width, height = self.size  # Get the screen size
                circle_size = min(width, height) * 0.3  # Calculate the circle size as 10% of the smaller dimension of the screen
                color = Color(random.random(),random.random() ,random.random() ,1.0) #random color for the circle
                circle = Ellipse(pos=(touch.x - circle_size/2, touch.y - circle_size/2), size=(circle_size, circle_size))
                self.circles[touch.id] = (color, circle)
                self.beat_animation(circle)


    def beat_animation(self, circle):
        anim = Animation(size=(circle.size[0]*1.2, circle.size[1]*1.2), duration=0.5)
        anim += Animation(size=(circle.size[0], circle.size[1]), duration=0.5)
        anim.repeat = True
        anim.start(circle)


    def on_touch_move(self, touch):
        width, height = self.size  # Get the screen size
        circle_size = min(width,height) * 0.3  # Calculate the circle size as 10% of the smaller dimension of the screen
        if touch.id in self.circles:
            color, circle = self.circles[touch.id]
            circle.pos = (touch.x - circle_size/2, touch.y - circle_size/2)

    def on_touch_up(self, touch):
        if touch.id in self.circles:
            color, circle = self.circles.pop(touch.id)
            self.canvas.remove(color)
            self.canvas.remove(circle)

class MultiTouchApp(App):
    def build(self):
        return Touch()

if __name__ == "__main__":
    MultiTouchApp().run()

我尝试像这样添加更改:

    def beat_animation(self, circle, touch):
        anim = Animation(pos=(touch.x - circle.size[0] / 2, touch.y - circle.size[1] / 2),size=(circle.size[0] * 1.2, circle.size[1] * 1.2), duration=0.5)
        anim += Animation(pos=(touch.x - circle.size[0] / 2, touch.y - circle.size[1] / 2),size=(circle.size[0] / 1.2, circle.size[1] / 1.2), duration=0.5)
        anim.repeat = True
        anim.start(circle)

但是当我停止移动手指时,圆圈只是跳回到最初创建的位置(我认为这是因为传递给beat_animation的触摸参数没有动态变化),我不知道如何修复它

python android animation graphics kivy
1个回答
0
投票

解决此类问题的一般方法是使用充当动画和画布指令之间中介的属性。

在这种情况下,我认为实现你想要的最简单的方法是将每个圆圈分成一个单独的小部件并使用

FloatLayout
作为父级:

import random

import kivy
from kivy.app import App
from kivy.animation import Animation
from kivy.graphics import Ellipse, Color
from kivy.properties import ListProperty, ColorProperty, NumericProperty, ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget


class BeatingTouchCircle(Widget):    
    radius = NumericProperty(1)
    position = ListProperty([0, 0])
    color = ColorProperty((0, 0, 0, 1))
    
    def __init__(self, radius, position, color, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.radius = radius
        self.position = position
        self.color = color
        
        with self.canvas:
            Color(rgba = self.color)
            self.circle = Ellipse(
                pos = (self.position[0] - self.radius, self.position[1] - self.radius),
                size = (self.radius * 2, self.radius * 2)
                )
            
        self.beat_animation()
        self.bind(radius=self.on_radius_changed)
        
    def beat_animation(self):
        anim = Animation(radius = self.radius * 1.2, duration = 0.5)
        anim += Animation(radius = self.radius, duration = 0.5)
        anim.repeat = True
        anim.start(self)
        
    def on_radius_changed(self, *_):
        self.circle.size = (self.radius * 2, self.radius * 2)
        self.circle.pos = (self.position[0] - self.radius, self.position[1] - self.radius)        



class Touch(FloatLayout):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.circles = {}  # Dictionary to store circles for each finger

    def on_touch_down(self, touch):
        if touch.id not in self.circles:
            radius = min(self.size) * 0.15
            color = (random.random(),random.random() ,random.random() ,1.0) #random color for the circle
            circle = BeatingTouchCircle(radius, (touch.x, touch.y), color)
            self.circles[touch.id] = (circle, touch)
            self.add_widget(circle)
            
    def on_touch_move(self, touch):
        if circle := self.circles.get(touch.id):
            circle, touch = circle
            circle.position = (touch.x, touch.y)
            
    def on_touch_up(self, touch):
        if circle := self.circles.get(touch.id):
            self.remove_widget(circle[0])
            del self.circles[touch.id]
            

class MultiTouchApp(App):
    def build(self):
        return Touch()

if __name__ == "__main__":
    MultiTouchApp().run()

© www.soinside.com 2019 - 2024. All rights reserved.