Беспорядок испортит анимацию
Беспорядок не делает полную анимацию.
Это мой текущий код:
from gi.repository import Clutter, Gtk
import sys
def onClick(actor, event):
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [280]) # clutter does not seem to be running this line
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [20])
def main():
Clutter.init(sys.argv)
# Colors
red = Clutter.Color().new(255, 0, 0, 255)
black = Clutter.Color().new(0, 0, 0, 255)
# Create Stage
stage = Clutter.Stage()
stage.set_title("Basic Usage")
stage.set_size(400, 200)
stage.set_color(black)
# Rectangle Actor
actor = Clutter.Rectangle()
actor.set_size(100, 50)
actor.set_position(150, 100)
actor.set_color(red)
actor.set_reactive(True)
actor.connect("button-press-event", onClick)
# Add Actor to the Stage
stage.add_actor(actor)
stage.connect("destroy", lambda w: Clutter.main_quit())
stage.show_all()
Clutter.main()
if __name__ == '__main__':
main()
Вот эта иллюстрация моей проблемы:
Для тех из вас, кто не любит гифки, вот моя проблема, описанная словами: я хочу, чтобы актер переместился из середины вправо, а затем влево. Вместо этого он просто движется от середины прямо влево.
Что вызывает это, и как я могу это исправить?
3 ответа
Как документация для ClutterActor.animate() говорит:
Вызов этой функции для актера, который уже анимируется, приведет к изменению текущей анимации с новыми конечными значениями, новым режимом замедления и новой продолжительностью https://developer.gnome.org/clutter/stable/clutter-Implicit-Animations.html
что означает, что следующий код:
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [280])
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [20])
в точности эквивалентно:
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [20])
это то, что вы видите.
если вы хотите связать две анимации, вы должны подключиться к completed
сигнал о ClutterAnimation
, с использованием connect_after
функция, так что Clutter может создать новую анимацию:
def moveLeft (animation, actor):
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [20])
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [280]).connect_after('completed', moveLeft)
Я хотел бы отметить, что animatev()
а также ClutterAnimation
устарели; они могут быть заменены с помощью явного Clutter.KeyframeTransition
или неявный переход, например:
from gi.repository import Clutter
Clutter.init(None)
stage = Clutter.Stage()
stage.connect('destroy', lambda x: Clutter.main_quit())
actor = Clutter.Actor()
actor.set_background_color(Clutter.Color.get_static(Clutter.StaticColor.RED))
actor.set_reactive(True)
actor.set_size(32, 32)
stage.add_child(actor)
actor.set_position(82, 82)
def moveLeft(actor):
actor.set_x(20)
def moveRight(actor):
actor.set_easing_duration(1000)
actor.set_easing_mode(Clutter.AnimationMode.LINEAR)
actor.set_x(280)
actor.connect('transition-stopped::x', lambda a, n, t: moveLeft(actor))
actor.connect('button-press-event', lambda a, e: moveRight(actor))
stage.show()
Clutter.main()
это может быть произвольно более сложным, чем это; Вы также должны помнить, чтобы отключить transition-stopped::x
обработчик сигнала и восстановите состояние замедления, чтобы избежать создания неявных анимаций каждый раз, когда вы изменяете состояние актера, но я оставлю это в качестве упражнения для читателя.
Попробуйте следующий код:
def onClick(actor, event):
animation1 = actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [280])
animation1.connect_after(
'completed',
lambda animation: actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [20])
)
Когда вы делаете это на линии сразу после друг друга
def onClick(actor, event):
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [280])
actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [20])
Беспорядок делает их обоих, не дожидаясь, пока другой закончит. Это означает, что первая команда почти не успевает переместить агента, прежде чем вторая команда вступит во владение.
Вот пример использования "завершенного" сигнала:
def onClick(actor, event):
animate(actor)
def animate(actor):
firstAnimation = actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [280])
firstAnimation.connect_after("completed", moveLeft)
def moveLeft():
self.actor.animatev(Clutter.AnimationMode.LINEAR, 1000, ["x"], [20])
Вот документация по анимации беспорядка
Вот документация по "выполненному" сигналу
Вот пример рабочего кода