Reputation: 19
I have this code that creates a MDLabel
with ButtonBehavior
and RotateBehavior
.
When the rotate_value_angle
is set to 0, I can animate the MDLabel
's height from 500 to 250.
When I change the angle to 90, the MDLabel
rotates anti-clockwise, as expected.
The problem I'm experiencing is that with the rotate_value_angle
at 90 degrees,
both the height and width of the MDLabel
are animated. I want to animate the MDLabel
's
'height', which would be the left side of it, to move from left to right
while maintaining its anchor point at the bottom-right corner.
Essentially, the movement of the MDLabel
should be similar to the movement when
the rotate_value_angle
is set at 0 but with the phone tilted 90 degrees anti-clockwise.
Thanks in advance.
Here's my Kivy
MDScreen:
RotateLabel:
id: label
size_hint: None, None
size: 300, 500
pos: 210, 470
text: "Hello World!"
on_release: app.change_rotate(self)
md_bg_color: "red"
Python
class RotateLabel(ButtonBehavior, RotateBehavior, MDLabel):
pass
class Test(MDApp):
def build(self):
return Builder.load_string(kv)
def change_rotate(self, instance_button: RotateLabel) -> None:
# angle = choice([i * 45 for i in range(8)])
anim = Animation(
# rotate_value_angle = 0
rotate_value_angle = 90,
d = 1)
anim.bind(on_start = self.change_label_height)
anim.start(instance_button)
def change_label_height(self, *args):
label = self.root.ids.label
if label.size == [300, 500]:
anim = Animation(
height = 250,
d = 2
)
anim.start(label)
else:
anim = Animation(
height = 500,
d = 2
)
anim.start(label)
Test().run()
Upvotes: 0
Views: 22
Reputation: 38822
I think the problem is that RotateBehavior
rotates the widget about its center, which causes the behavior you are seeing. There doesn't seem to be any way to change the rotation origin when using RotateBehavior
. You can change your RotateLabel
definition without using RotateBehavior
like this:
class RotateLabel(ButtonBehavior, MDLabel):
rotate_value_angle = NumericProperty(0)
rot_matrix = ObjectProperty(Matrix())
def on_rotate_value_angle(self, *args):
self.rot_matrix.identity()
self.rot_matrix.rotate(radians(-self.rotate_value_angle), 0, 0, 1)
def collide_point(self, x, y):
if self.rotate_value_angle == 0:
return super(RotateLabel, self).collide_point(x, y)
else:
x1 = x - self.x
y1 = y - self.y
x2, y2, z2 = self.rot_matrix.transform_point(x1, y1, 0)
x3 = x2 + self.x
y3 = y2 + self.y
return self.x <= x3 <= self.right and self.y <= y3 <= self.top
The above code handles the rotation and modifies the collide_point()
method (which is used for button clicks) to account for the rotation.
The kv
must also be modified for this to work:
MDScreen:
RotateLabel:
id: label
size_hint: None, None
size: 300, 500
pos: 210, 470
text: "Hello World!"
on_release: app.change_rotate(self)
md_bg_color: "red"
canvas.before:
PushMatrix:
Rotate:
angle: self.rotate_value_angle
axis: 0, 0, 1
origin: self.pos
canvas.after:
PopMatrix:
The above code does the rotation about the pos
of the RotateLabel
instead of its center.
Upvotes: 0