使用自定义宽度为 Kivy Bezier 曲线制作动画? (有点傻的问题)

animate Kivy Bezier curve with custom width ? (a bit silly question)

更新:在与其他人讨论后,我认为这是一个有点愚蠢的问题。我想为改变宽度的贝塞尔曲线制作动画,但它没有宽度 属性。使用 Line Bezier,我可以更改宽度,但无法设置动画。


我无法像 Line 那样改变 Bezier 曲线的 witdh
这是代码:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import *

class MyLayout(Widget):
    def __init__(self):
        super(MyLayout, self).__init__()
        with self.canvas:
            self.L=Bezier(points=[200,450,500,300,600,150],width=12)
            self.k=Line  (bezier=[100,350,400,200,500,50 ],width=12)

class MyApp(App):
    def __init__(self):
        super(MyApp, self).__init__()
    def build(self):
        return MyLayout()

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

并输出:

问题是,

上面的曲线不是 width=12

我认为那是因为 Kivy 的贝塞尔 Class 没有属性 width 因为当我在 kv lang 上这样做时,它给了我 AttributeError: 'kivy.graphics.vertex_instructions.Bezier' object has no attribute 'width'。那么,为什么不使用 Linebezier 呢?我想在其上使用 Animation,当我尝试在 Line 上使用 bezier 时,我得到 AttributeError: attribute 'bezier' of 'kivy.graphics.vertex_instructions.Line' objects is not readable.

所以这个问题,

如何更改 Bezierwidth。如果不可能,是否有任何方法可以找到给定 x 的 cruve(或 ys)的 y 以便我可以将 Ellipse 放在这些点上并调整它们的大小以模拟宽度?

谢谢并原谅我的英语

Bezier没有width属性,但是Line有。所以你可以为 width 设置动画。一个简单的方法是通过动画 NumericProperty 来保持宽度。这是您的代码的修改版本:

from kivy.animation import Animation
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.uix.widget import Widget
from kivy.graphics import *

class MyLayout(Widget):
    line_width = NumericProperty(12)
    def __init__(self):
        super(MyLayout, self).__init__()
        with self.canvas:
            self.L=Bezier(points=[200,450,500,300,600,150],width=self.line_width)
            self.k=Line  (bezier=[100,350,400,200,500,50 ],width=self.line_width)

    def on_line_width(self, instance, new_width):
        self.k.width = new_width

class MyApp(App):

    def build(self):
        Clock.schedule_once(self.anim)
        return MyLayout()

    def anim(self, dt):
        a = Animation(line_width=3)
        a.start(self.root)

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

如果您在 kv 中构建 Line,那么您甚至不需要 on_line_width() 方法,因为 kivy 会为您进行绑定。

线路可以使用bezier:,例如:

Line:
    bezier:[n1,n2,n3,n4]
    width:3

这是 Line,而不是 Bezier,但您得到的结果相同...

一个例子:

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout

posicao=[]
class Draw(BoxLayout):
    def __init__(self, **kwargs):
        super(Draw, self).__init__(**kwargs)
    
    def on_touch_down(self,touch):
        posicao.append(touch.pos)
        
    def on_touch_up(self,touch):
        posicao.clear()
        
    def on_touch_move(self,touch):
        Line = Builder.load_string(
"""
FloatLayout:
    canvas:
        Color:
            rgba:11,.1,1,1
        Line:
            points: {pos}
            width:14
""".format(pos=(touch.pos, posicao[0])))
        self.add_widget(Line)
        posicao.clear()
        posicao.append(touch.pos)
        
class Code(App):
    def build(self):
        return Draw()
        
if __name__ == '__main__':
    Code().run()

我 或者:

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import *

posi = []

Builder.load_string(
"""
<Draw>:
    
""")
class Draw(BoxLayout):
    def __init__(self, **kwargs):
        super(Draw, self).__init__(**kwargs)
    
    def on_touch_down(self,touch):
        posi.clear()
        posi.append(touch.pos)
        
    def on_touch_up(self,touch):
        posi.clear()
        
    def on_touch_move(self,touch):
        with self.canvas:
            Line(points=[posi[0], touch.pos],width=14)
        posi.clear()
        posi.append(touch.pos)
            
class Code(App):
    def build(self):
        return Draw()
        
if __name__ == '__main__':
    Code().run()