Kivy - 贝塞尔曲线



本章中,我们将创建一个Kivy应用程序,它将沿着点的列表交互式地绘制一条贝塞尔曲线。如果使用以下代码段计算出的x和y坐标绘制一条封闭曲线,则生成的图形类似于吃豆人角色:

from math import cos, sin, radians

x = y = 300
z = 200

self.points = [x, y]
for i in range(45, 360, 45):
   i = radians(i)
   self.points.extend([x + cos(i) * z, y + sin(i) * z])

   with self.layout.canvas:
      Color(1.0, 0.0, 1.0)
      self.line = Line(
         points=self.points + self.points[:2],
         dash_offset=10, dash_length=100
      )

它生成如下所示的线型:

Kivy Bezier

然后,我们使用相同的点列表绘制一条贝塞尔曲线。

Color(1.0, 0.0, 1.0)
self.line = Line(
   points=self.points + self.points[:2],
   dash_offset=0,
   dash_length=100
)

直线和贝塞尔曲线将显示如下:

Kivy Bezier Line

现在我们想动态地构建这两条曲线。我们使用两个滑块来更改线指令和贝塞尔曲线指令的虚线长度和偏移值,因为每个滑块的值属性会随着以下事件处理程序而变化:

def _set_bezier_dash_offset(self, instance, value):
   # effect to reduce length while increase offset
   self.bezier.dash_length = 100 - value
   self.bezier.dash_offset = value
   
def _set_line_dash_offset(self, instance, value):
   # effect to reduce length while increase offset
   self.line.dash_length = 100 - value
   self.line.dash_offset = value

因此,更改滑块的值以查看两条曲线是如何动态重绘的。

示例

完整的代码如下:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.slider import Slider
from kivy.graphics import Color, Bezier, Line
from kivy.core.window import Window

Window.size = (720,400)

class Main(App):
   title='Bezier Example'
   def _set_bezier_dash_offset(self, instance, value):
      # effect to reduce length while increase offset
      self.bezier.dash_length = 100 - value
      self.bezier.dash_offset = value
      
   def _set_line_dash_offset(self, instance, value):
      # effect to reduce length while increase offset
      self.line.dash_length = 100 - value
      self.line.dash_offset = value
   
   def build(self):
      from math import cos, sin, radians
      x = y = 300
      z = 200
      # Pacman !
      self.points = [x, y]
      for i in range(45, 360, 45):
         i = radians(i)
         self.points.extend([x + cos(i) * z, y + sin(i) * z])
      print (self.points)
      self.layout = FloatLayout()
      
      with self.layout.canvas:
         Color(1.0, 0.0, 0.0)
   
         self.bezier = Bezier(
            points=self.points, segments=150, loop=True,
            dash_length=100, dash_offset=10
         )
   
         Color(1.0, 0.0, 1.0)
         self.line = Line(
            points=self.points + self.points[:2],
            dash_offset=10,
            dash_length=100)
      l1=Label(
         text='Beizer offset', pos_hint={'x':.1},
         size_hint=(.1, None), height=50
      )
      self.layout.add_widget(l1)
   
      s1 = Slider(
         y=0, pos_hint={'x': .3},
         size_hint=(.7, None), height=50
      )
      self.layout.add_widget(s1)
      s1.bind(value=self._set_bezier_dash_offset)
      
      l2=Label(
         text='Line offset', y=50, pos_hint={'x':.1},
         size_hint=(.1, None), height=50
      )
      self.layout.add_widget(l2)
      
      s2 = Slider(
         y=50, pos_hint={'x': .3},
         size_hint=(.7, None), height=50
      )
      self.layout.add_widget(s2)
      s2.bind(value=self._set_line_dash_offset)
      
      return self.layout

if __name__ == '__main__':
   Main().run()

输出

以下屏幕截图显示了在两个不同滑块位置的曲线:

Kivy Bezier Curves Kivy Bezier Offset
广告