只是个人学习的时候的一些笔记,如果有什么错误的地方还请各位勿喷,手下留情,期待您的指正。 定期会更新文章到www.sea-whales.cn我的个人网站中,有兴趣的小伙伴可以进来看看
旋转、平移和缩放空间坐标
在canvas 中是可以使用Rotate
指令来控制旋转操作,他与ScatterLayout
布局不同,它是对整个坐标空间,因此所有的子部件都是会受到影响。在使用整个参数时,需要指定三个参数;
- axis: 设置用于旋转的轴,通常为z轴(0,0,1)
- angle: 设置旋转度数
- origin: 设置旋转参考点
来试试效果:
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# 选择平移缩放
from kivy.uix.gridlayout import GridLayout
from kivy.app import App
class RotateGridLayoutWidget(GridLayout):
def __init__(self, **kwargs):
super(RotateGridLayoutWidget, self).__init__(**kwargs)
class RotateTranslateZoomApp(App):
def build(self):
return RotateGridLayoutWidget()
if __name__ == '__main__':
RotateTranslateZoomApp().run()
rotatetranslatezoom.kv
<MyImage@Image>
source:'rotatetranslatezoom.jpg'
pos: self.parent.pos
size_hit: .5, .4
canvas:
Color:
rgba: 1,0,0,.5
Line:
rectangle: self.x, self.y, self.width,self.height
<RotateGridLayoutWidget>
cols: 2
canvas:
Color:
rgba:(1,1,1,1)
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'col:1 row:1'
FloatLayout:
canvas:
Rotate:
axis:(0,0,1)
angle: 60
origin: self.center
Color:
rgba:(1,1,1,1)
Rectangle:
pos: self.pos
size: self.size
MyImage:
Button:
text: 'col:1 row:2'
以上布局,会出现两个按钮和一张图片。其中按钮按列排列。但是由于我们在FloatLayout
中使用了Rotate
这样导致了画布进行了旋转。我们看到的效果是图像是沿着中点,逆时针旋转了60度的情况。并且由于旋转的是在Button前面加入的,所以导致后方的空间坐标系也收到了影响,也连带着旋转了。而且点击第二个按钮黑色部分发现无效。而是需要点击按钮本身的位置,也就是第一个按钮的垂直排列的列下方才有效。为了避免这个情况,我们需要引入两个新的命令。
- PushMatrix : 保存上下文环境。
- PopMatrix : 恢复上下文环境。
就像上面的栗子:
我们在对某个图像的画布或者其他进行操作的时候。就会导致代码排序在它之后的内容受到影响。这个时候我们就可以使用前面两个命令对环境进行保存和回复。
我们来改下KV文件:
<MyImage@Image>
source:'rotatetranslatezoom.jpg'
pos: self.parent.pos
size_hit: .5, .4
canvas:
PushMatrix
Rotate:
axis:(0,0,1)
angle: 60
origin: self.center
Color:
rgba: 1,0,0,.5
Line:
rectangle: self.x, self.y, self.width,self.height
PopMatrix
<RotateGridLayoutWidget>
cols: 2
canvas:
Color:
rgba:(1,1,1,1)
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'col:1 row:1'
FloatLayout:
MyImage:
Button:
text: 'col:1 row:2'
以上文件运行后,会发现,红色矩形框旋转了60度。后面的按钮以及图像均不会受到影响,这是因为Rotate
指令我们是放在canvas
中的,是在屏幕上以及确定位置之后才开始执行的,并且在显示的时候,就使用前面的恢复环境命令恢复了。但是我们旋转的时候,就是为了让图像旋转。现在的情况却是图像并未旋转,这个时候,可以来试试前面我们学过的属性canvas.befor
和canvas.after
我们只需要在位置还没确定的时候,就旋转,这样图像就会在画布旋转之后进行图像的显示。这样就能达到指定效果了。我们在改动下KV文件:
<MyImage@Image>
source:'rotatetranslatezoom.jpg'
pos: self.parent.pos
size_hit: .5, .4
canvas.before: # 使用canvas.before 命令
PushMatrix # 保存当前上下文环境
Rotate:
axis:(0,0,1) # 旋转
angle: 60 # 角度
origin: self.center # 起点
canvas:
Color:
rgba: 1,0,0,.5
Line:
rectangle: self.x, self.y, self.width,self.height
canvas.after:
PopMatrix # 恢复上下文环境
<RotateGridLayoutWidget>
cols: 2
canvas:
Color:
rgba:(1,1,1,1)
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'col:1 row:1'
FloatLayout:
MyImage:
Button:
text: 'col:1 row:2'
使用上面的kv文件,就会发现图像和矩形框都一起旋转了。这样就达到了,旋转的同时连小部件也旋转。当然会发现我们为什么不把PopMatrix
写在canvas
的末行,而是大费周章的写个canvas.after
,这里我就不解释了结合前面的知识点,大家可以尝试下,将PopMatrix
写在canvas末行,看看是什么效果。
试过了旋转,我们来看看平移:
canvas
平移指令是Translate
除了属性以外,该指令和我们前面用的Rotate
指令基本是一致。
在使用Translate
时,是需要指定X轴,Y轴,Z轴上的移动距离,如果不指定,则默认不移动。我们再拿前面的旋转代码给他加上平移属性看看。
Translate:
x: -50
y: 100
z:0
就不贴完整代码了,大概就是在Rotate属性结束下方另起一行,加上以上四行代码。我们会发现,图片的位置会向左平移了50个像素,将按钮盖住了,并且也向上移动了100个像素。如果这里我们将z轴的值进行改变,会发现图像不见了,这是因为图像的位置已经不在画布上了。
同理缩放(Scale)也是和前面一致,我们只需要指定xyz轴上的缩放倍数即可:
Scale:
xyz:(1.25,1.30,0.5)
如上,则是x轴和y轴分别缩放1.25和1.30.倍,z轴缩放0.5倍。