歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> 關於Linux >> 使用Moblin進行應用程序開發——Clutter之動畫

使用Moblin進行應用程序開發——Clutter之動畫

日期:2017/2/25 12:02:40   编辑:關於Linux

  正文開始之前先說幾句別的。上月20號發布的Moblin V2 Beta版中,Clutter的版本已經到了0.9,API與clutter 0.8相比有了些變化,兩者在API上已不兼容。鑒於pyclutter目前版本依然還是0.8,並且本系列博文更側重於概念,因此所用的API一律基於clutter 0.8。等clutter 1.0正式版本發布後,我們再來看API的變化。

  之前講了一點有關Actor與Stage的內容,有了演員和舞台,接下來自然而然就要上台表演,也就是這裡所謂的動畫了。在Clutter的動畫中,有三個概念不得不提一下,他們是——Timeline,Alpha和Behaviour。

  Timeline,即時間軸,也就是表演的時間段,這個概念我想大家應該都能明白,不多廢話了。Behaviour,即行為,也就是表演的內容,比如放大、縮小、旋轉、透明化等等均屬於行為的范疇。最後講講Alpha,這個詞挺難翻譯的,如果放到表演上來理解,Alpha所指的應該是表演方式。比如同樣是將某個Actor放大2倍,通過Alpha可以控制是采用線性放大,加速放大還是減速放大等效果。Alpha其實是一個與總幀數和當前幀相關的函數,它的返回值是一個介於0和ALPHA_MAX之間的數,每當一個新的幀產生時都會調用Alpha函數,通過Alpha函數的返回值來確定當前幀的變化。用戶可以自定義Alpha函數,也可以使用clutter提供的一些常用Alpha函數。

  一般來說,基於clutter進行動畫編程,代碼結構通常是這樣的:

  1. 創建時間軸ClutterTimeline

  2. 創建ClutterAlpha

  3. 創建ClutterBehaviour

  4. 將Behaviour應用到Actor上

  5. 啟動時間軸

  目前Clutter提供的Behaviour包括有Bspline、Ellipse、Depth、Opacity、Path、Rotate和Scale。如果用戶覺得這些Behaviour無法滿足應用的需求,可以通過實現自定義Behaviour或者使用Timeline的new-frame事件來制作自定義的動畫效果。

  回到以前使用的demo 程序——照片浏覽器上來,這次要添加的功能是相片的正中顯示。之前照片是以隨機方位和角度鋪在桌面上,現在通過雙擊照片,圖片將以動畫的形式移至窗口正中並轉至0度。單擊正中顯示照片將使圖片以動畫形式回到原先的位置。

  代碼如下:

  #!/usr/bin/python

  import sys

  import os

  import random

  import clutter

  STAGE_WIDTH=1024

  STAGE_HEIGHT=768

  Dragging = False

  DraggingPhoto = None

  Center = False

  pic_list = []

  timeline = None

  alpha = None

  p_behavior = None

  r_behavior = None

  class Photo:

  '''Photo class'''

  border_width = 10

  def __init__(self, path, stage):

  self.stage = stage

  self.path = path

  self.x = 0

  self.y = 0

  self.degree = 0

  self.drag_start_x = 0

  self.drag_start_y = 0

  self.pic = clutter.Texture()

  self.pic.set_from_file(path)

  self.width = self.pic.get_width()+2*Photo.border_width

  self.height = self.pic.get_height()+2*Photo.border_width

  self.frame = clutter.Rectangle()

  self.frame.set_color(clutter.Color(0xff, 0xff, 0xff, 0xff))

  self.frame.set_position(self.x, self.y)

  self.frame.set_size(self.width, self.height)

  self.group = clutter.Group()

  self.group.add(self.frame)

  self.group.add(self.pic)

  self.pic.set_position(Photo.border_width, Photo.border_width)

  self.stage.add(self.group)

  self.group.set_reactive(True)

  self.group.connect("button-press-event", self.on_button_press)

  self.group.connect("button-release-event", self.on_button_release)

  self.group.connect("motion-event", self.on_motion)

  def set_random_position(self):

  stage_width = self.stage.get_width()

  stage_height = self.stage.get_height()

  left = random.randint(0, stage_width)

  top = random.randint(0, stage_height)

  degree = random.randint(0, 360)

  self.set_position(left, top, degree)

  def set_position(self, x, y, degree):

  self.x = x

  self.y = y

  self.degree = degree

  self.group.set_position(x, y)

  self.group.set_rotation(clutter.Z_AXIS, degree, self.width/2, self.height/2, 0)

  def on_button_press(self, actor, event):

  global Dragging, DraggingPhoto, Center, timeline, alpha, p_behavior, r_behavior

  if event.button == 1 and event.click_count == 2 and Center == False:

  self.group.raise_top()

  for pic in pic_list:

  pic.group.set_reactive(False)

  self.group.set_reactive(True)

  timeline = clutter.Timeline(30, 30)

  alpha = clutter.Alpha(timeline, clutter.ramp_inc_func)

  tx = int((STAGE_WIDTH-self.width)/2)

  ty = int((STAGE_HEIGHT-self.height)/2)

  knots=((self.x, self.y), (tx, ty),)

  p_behavior = clutter.BehaviourPath(alpha, knots)

  p_behavior.apply(self.group)

  r_behavior = clutter.BehaviourRotate(clutter.Z_AXIS, self.degree, 0, alpha, True)

  r_behavior.set_center(self.width/2, self.height/2, 0)

  r_behavior.apply(self.group)

  timeline.start()

  Center = True

  return True

  if event.button == 1 and event.click_count == 1 and Center == True:

  for pic in pic_list:

  pic.group.set_reactive(True)

  timeline = clutter.Timeline(30, 30)

  alpha = clutter.Alpha(timeline, clutter.ramp_dec_func)

  tx = int((STAGE_WIDTH-self.width)/2)

  ty = int((STAGE_HEIGHT-self.height)/2)

  knots=((self.x, self.y), (tx, ty),)

  p_behavior = clutter.BehaviourPath(alpha, knots)

  p_behavior.apply(self.group)

  r_behavior = clutter.BehaviourRotate(clutter.Z_AXIS, self.degree, 0, alpha, True)

  r_behavior.set_center(self.width/2, self.height/2, 0)

  r_behavior.apply(self.group)

  timeline.start()

  Center = False

  return True

  if event.button == 1 and Dragging == False and Center == False:

  Dragging = True

  DraggingPhoto = self

  self.drag_start_x = event.x

  self.drag_start_y = event.y

  self.group.raise_top()

  return True

  return False

  def on_motion(self, actor, event):

  global Dragging, DraggingPhoto

  if event.modifier_state & clutter.BUTTON1_MASK and Dragging == True and DraggingPhoto == self:

  dist_x = event.x - self.drag_start_x

  dist_y = event.y - self.drag_start_y

  self.group.move_by(dist_x, dist_y)

  self.drag_start_x = event.x

  self.drag_start_y = event.y

  return True

  return False

  def on_button_release(self, actor, event):

  global Dragging, DraggingPhoto

  if event.button == 1:

  Dragging = False

  DraggingPhoto = None

  return True

  return False

  def main(args):

  if len(args) < 2:

  print "The number of arguments is less than 2!"

  return -1

  path=args[1]

  if not os.path.exists(path):

  print path, "doesn't exist!"

  return -1

  stage = clutter.Stage()

  stage.set_size(STAGE_WIDTH, STAGE_HEIGHT)

  stage.set_color(clutter.Color(0x00, 0x00, 0x00, 0x00))

  stage.connect("destroy", clutter.main_quit)

  if not path.endswith(os.sep):

  path+=os.sep

  filelist = os.listdir(path)

  for item in filelist:

  pic=Photo(path+item, stage)

  pic.set_random_position()

  pic_list.append(pic)

  stage.show_all()

  clutter.main()

  if __name__ == '__main__':

  main(sys.argv)

Copyright © Linux教程網 All Rights Reserved