ต่อจาก
บทที่ ๒
หลังจากที่ได้แนะนำคำสั่งที่ใช้ในการสร้างภาพใน manim ไปแล้ว บทต่อจากนี้จะเป็นการลงลึกเรื่องส่วนประกอบต่างๆของภาพ
งานหลักของ manim คือการสร้างภาพเคลื่อนไหว แต่ก่อนจะไปถึงตรงนั้น ในบทนี้จะเริ่มที่เรื่องของพื้นฐานการสร้างและจัดวางวัตถุต่างๆในภาพ แล้วจึงค่อยเริ่มไปทำภาพเคลื่อนไหวใน
บทที่ ๕
การสร้างและใส่วัตถุ MObject
MObject (m ในที่นี้ย่อมาจาก math) คือวัตถุพื้นฐานที่เป็นองค์กระกอบหลักภายในภาพของ manim
MObject มีอยู่หลากหลายชนิด เช่นตัวหนังสือ สูตรคณิตศาสตร์ กราฟ รูปร่างต่างๆ ฯลฯ
ใน manim ถ้าพูดถึง "วัตถุ" โดยทั่วไปก็จะหมายถึง MObject นี้ดังนั้นต่อไปจะเรียกง่ายๆว่า "วัตถุ"
วัตถุเหล่านี้สร้างขึ้นทำได้โดยสร้างจากคลาส เช่นตัวหนังสือคือออบเจ็กต์คลาส Text สูตรคณิตศาสตร์เป็นออบเจ็กต์ของคลาส Tex และสี่เหลี่ยมจตุรัส สามเหลี่ยม วงกลม เป็นออบเจ็กต์ในคลาส Square Triangle Circle เป็นต้น
วัตถุต่างๆที่สร้างขึ้นมาจัดวางเป็นองค์ประกอบภายในภาพของ manim ล้วนเป็นออบเจ็กต์ที่สร้างจากคลาสย่อยของคลาส MObject
แต่แค่สร้างวัตถุขึ้นมาเฉยๆจะยังไม่ปรากฏให้เห็นได้ในภาพ แต่จะปรากฏขึ้นเมื่อมีคำสั่งหรือเหตุการณ์อะไรบางอย่างทำให้มันปรากฏขึ้นมา
วิธีการทำให้วัตถุปรากฏในภาพนั้นมีอยู่หลายวิธี สำหรับในบทนี้จะพูดถึงวิธีที่ง่ายที่สุดคือใส่ลงไปเฉยๆให้ปรากฏในทันที (ยังไม่ทำเป็นภาพเคลื่อนไหว) โดยใช้เมธอด self.add() โดยใส่วัตถุทั้งหมดที่ต้องการให้ปรากฏลงไปด้วยกันทีเดียวเลย
ตัวอย่าง ลองสร้างวัตถุแต่ละชนิดขึ้นมาแล้วใส่ลงในภาพทั้งหมด
import manimlib as mnm
class Manimala(mnm.Scene):
def construct(self):
samliam = mnm.Triangle(color='#FF6622')
samakan = mnm.Tex(r'4 \times 3 = 12',color='#22FF99')
khokhwam = mnm.Text('มณีมาลา',color='#8888FF')
self.add(khokhwam,samliam,samakan)
ภาพที่ได้
จะเห็นว่าวัตถุถูกวาดทับลงไปเรื่อยๆ ลำดับการวาดก่อนหลังจะขึ้นอยู่กับลำดับที่ใส่ใน self.add() ในที่นี้คือ ข้อความ (Text) > สามเหลี่ยม (Triangle) > สมการ (Tex)
รายละเอียดของวัตถุแต่ละชนิดจะยังไม่พูดถึงตอนนี้ แต่จะค่อยๆอธิบายเพิ่มเติมในบทถัดๆไป ตอนนี้จะพูดถึงลักษณะโดยรวมของ MObject ก่อน
ปกติเมื่อใส่ลงไปวัตถุทั้งหมดจะอยู่ตรงกลางของภาพ คือตำแหน่ง x=0,y=0 ต้องทำการจัดเรียงหรือย้ายตำแหน่งจึงจะไปอยู่ตำแหน่งที่ต้องการ ซึ่งจะกล่าวถึงต่อไป
การกำหนดพิกัดตำแหน่งวัตถุด้วยเมธอด .move_to()
วิธีการจัดวางตำแหน่งของวัตถุนั้นมีอยู่หลายวิธี โดยพื้นฐานแล้วที่ง่ายที่สุดคือใช้เมธอด .set_x(), .set_y() หรือ .move_to() ที่ตัวออบเจ็กต์หลังจากที่สร้างขึ้นมาแล้ว
โดย .set_x() จะเป็นการกำหนดตำแหน่งในแนวนอน .set_y() กำหนดตำแหน่งแนวตั้ง ส่วน .move_to() จะกำหนดตำแหน่งทั้งสองแนวไปพร้อมกัน
ค่าที่ต้องใส่ใน .move_to() คืออาเรย์ที่มีเลข ๓ ตัว ซึ่งแสดงถึงพิกัดในสามมิติ แต่ในที่นี้จะเริ่มจากภาพสองมิติ ซึ่งก็จะใช้แค่ x,y คือ ๒ ตัวแรก ส่วนอีกตัวคือค่าแกน z ในที่นี้ยังไม่ใช้จึงอาจใส่เป็น 0 ไว้ก็ได้
ตัวอย่างการใช้ .set_x(), .set_y() และ .move_to()
import manimlib as mnm
import numpy as np
class Manimala(mnm.Scene):
def construct(self):
text1 = mnm.Text('ก',color='#e0afdd')
text1.set_x(5)
text2 = mnm.Text('ข',color='#afd3e0')
text2.set_y(-2)
text3 = mnm.Text('ค',color='#b5e0af')
text3.move_to(np.array([-5,2,0]))
text4 = mnm.Text('ง',color='#e0c9af')
self.add(text1,text2,text3,text4)
อนึ่ง ขนาดภาพนั้นโดยค่าตั้งต้นแล้วคือกว้าง 14.2 หน่วย สูง 8 หน่วยพิกัดแกน x คือ -7.1 ถึง 7.1 แกน y คือ -4 ถึง 4
การเลื่อนตำแหน่งวัตถุด้วยเมธอด .shift()
อีกวิธีที่ใช้มากในการเปลี่ยนตำแหน่งของวัตถุก็คือเลื่อนโดยอ้างอิงจากจุดเดิม โดยใช้เมธอด .shift()
ตัวอย่าง ลองสร้างวัตถุข้อความขึ้นมา ๕ ตัว แล้วจัดวางให้ไปอยู่ในตำแหน่งต่างๆ
import manimlib as mnm
class Manimala(mnm.Scene):
def construct(self):
text1 = mnm.Text('ก',color='#FF6666')
text1.shift(mnm.RIGHT*6)
text2 = mnm.Text('ข',color='#88FF22')
text2.shift(mnm.UP*3)
text3 = mnm.Text('ค',color='#88FFBB')
text3.shift(mnm.LEFT*6+mnm.DOWN*3)
text4 = mnm.Text('ง',color='#FFAA66')
text4.shift([1,-2,0])
text5 = mnm.Text('จ',color='#AACCEE')
self.add(text1,text2,text3,text4,text5)
เพื่อความเข้าใจง่าย ในที่นี้ใช้ค่าอาเรย์ที่ manim ได้เตรียมไว้สำหรับแทนตำแหน่งต่างๆซึ่งเอาไว้ใส่แทนที่จะสร้างอาเรย์หรือลิสต์โดยตรง
หลักๆที่ใช้กำหนดทิศทางมี ๘ ตัว คือ บน (UP) ล่าง (DOWN) ซ้าย (LEFT) ขวา (RIGHT) แล้วก็ทิศเฉียงที่เกิดจากการผสมกัน คือบนซ้าย (UL) บนขวา (DR) ล่างซ้าย (DL) ล่างขวา (DR)
print(mnm.LEFT) # ได้ [-1. 0. 0.]
print(mnm.RIGHT) # ได้ [1. 0. 0.]
print(mnm.UP) # ได้ [0. 1. 0.]
print(mnm.DOWN) # ได้ [ 0. -1. 0.]
print(mnm.UL) # ได้ [-1. 1. 0.]
print(mnm.UR) # ได้ [1. 1. 0.]
print(mnm.DL) # ได้ [-1. -1. 0.]
print(mnm.DR) # ได้ [ 1. -1. 0.]
การย้ายวัตถุไปติดขอบหรือมุมด้วยเมธอด .to_edge() หรือ .to_corner()
เมธอด .to_edge() และ .to_corner() ใช้สำหรับเลื่อนวัตถุไปสุดขอบหรือไว้ที่มุม โดยค่าที่ต้องใส่คืออาเรย์แสดงทิศที่ต้องการย้ายไป
ข้อแตกต่างของ .to_edge() กับ .to_corner() คือค่าตั้งต้น โดยถ้าไม่กำหนดทิศ .to_edge() จะเป็นการย้ายไปติดขอบซ้าย (LEFT) ส่วน .to_corner() จะเป็นการย้ายไปติดขอบซ้ายล่าง (UL) แต่หากกำหนดทิศลงไปไม่ว่าจะใช้เมธอดไหนผลก็จะเหมือนกัน
ตัวอย่าง
import manimlib as mnm
class Manimala(mnm.Scene):
def construct(self):
text1 = mnm.Text('ก')
text1.to_edge(mnm.UP)
text2 = mnm.Text('ข')
text2.to_edge(mnm.DOWN)
text3 = mnm.Text('ค')
text3.to_edge(mnm.LEFT)
text4 = mnm.Text('ง')
text4.to_edge(mnm.RIGHT)
text5 = mnm.Text('จ')
text5.to_edge(mnm.UR)
text6 = mnm.Text('ช')
text6.to_corner()
self.add(text1,text2,text3,text4,text5,text6)
การวางตำแหน่งโดยอิงจากวัตถุอื่นด้วยเมธอด .next_to()
อีกวิธีที่สะดวกในการวางวัตถุคือวางโดยอ้างอิงจากวัตถุอื่นที่ถูกวางไว้แล้ว
หากมีวัตถุหนึ่งถูกสร้างอยู่แล้ว และต้องการจะวางตำแหน่งวัตถุโดยขึ้นอยู่กับตำแหน่งวัตถุที่มีอยู่เดิมนั้นอาจใช้เมธอด .next_to() โดยใส่วัตถุที่ใช้อ้างอิงและใส่ทิศทางที่จะต่อ
ตัวอย่าง
import manimlib as mnm
class Manimala(mnm.Scene):
def construct(self):
text1 = mnm.Text('กลาง',color='#efb5e1')
text2 = mnm.Text('ขวา',color='#a6dcc2')
text2.next_to(text1,mnm.RIGHT)
text3 = mnm.Text('ล่าง',color='#cdaf97')
text3.next_to(text1,mnm.DOWN)
text4 = mnm.Text('ขวาบน',color='#9e9f8f')
text4.next_to(text2,mnm.UP)
text5 = mnm.Text('ขวาบนขวา',color='#e5c6f0')
text5.next_to(text4,mnm.RIGHT)
text6 = mnm.Text('ขวาบนขวาบน',color='#dbe5ee')
text6.next_to(text5,mnm.UP)
self.add(text1,text2,text3,text4,text5,text6)
จะเห็นว่าวัตถุถูกวางต่อกันไปเรื่อยๆตามทิศที่กำหนด
หากต้องการเพิ่มระยะให้เว้นห่างออกไปก็ใส่คีย์เวิร์ด buff กำหนดระยะห่างตามที่ต้องการ เช่น
import manimlib as mnm
class Manimala(mnm.Scene):
def construct(self):
text1 = mnm.Text('กลาง',color='#cd88af')
text2 = mnm.Text('ซ้าย',color='#efe1b5')
text2.next_to(text1,mnm.LEFT,buff=3.5)
text3 = mnm.Text('ขวาล่าง',color='#56ec2c')
text3.next_to(text1,mnm.DR,buff=1.5)
text4 = mnm.Text('ซ้ายบน',color='#9eef2f')
text4.next_to(text2,mnm.UP,buff=2.5)
self.add(text1,text2,text3,text4)
หากไม่ได้ใส่ค่า buff จะเป็นระยะห่างตั้งต้น คือเป็น buff=0.25
การคัดลอกวัตถุด้วยเมธอด .copy()
หากมีวัตถุอยู่ตัวหนึ่งแล้วต้องการสร้างอีกตัวให้เหมือนกันเลยก็ทำได้โดยใช้เมธอด .copy()
วัตถุที่สร้างโดย .copy() นั้นแค่หน้าตาเหมือนตัวต้นแบบเท่านั้น แต่ไม่ถือเป็นตัวเดียวกัน หลังจากสร้างแล้วจะนำไปทำอะไรก็ไม่มีผลต่อตัวต้นฉบับ
ตัวอย่าง ลองคัดลอกวัตถุมาแล้วย้ายไปวางตำแหน่งต่างไป
import manimlib as mnm
class Manimala(mnm.Scene):
def construct(self):
text = mnm.Text('สไลม์',color='#77aacc',size=2.9)
text.shift(mnm.UL*2)
textc = text.copy()
textc.shift(mnm.RIGHT*5)
textcc = textc.copy()
textcc.shift(mnm.DOWN*4)
self.add(text,textc,textcc)
อ่านบทถัดไป >>
บทที่ ๔