반응형
기본 사용법
아무 파라미터 없이 VerticalBarChart를 만들면, VerticalBarChart의 CONFIG에 지정되어 있는 샘플 데이터 및 파라미터 값으로 디폴트 바 차트가 만들어집니다.
단, 이때 is_add_bars=True로 해줘야 막대가 같이 나타납니다.
is_add_bars=False가 디폴트로, chart를 add하면 막대를 제외한 나머지가 화면에 표출되고, 막대는 chart.get_bar_animation()에 의해 얻어지는 애니메이션에 의해 표출됩니다.
from manimlib.imports import *
from src.comp.plot import VerticalBarChart
class SimpleTest(Scene):
def construct(self):
chart = VerticalBarChart(is_add_bars=True)
self.add(chart)
self.wait()
데이터 지정해서 막대 차트 만들기
데이터는 (막대 이름, 막대 값, 막대 칼라)인 튜플값이 모인 리스트로 전달해 주면 됩니다.
data = [
("Mullet", 30, RED), ("Mackerel", 50, RED),
("Salmon", 80, RED), ("Shark", 60, RED), ("Whale", 40, RED),
]
chart = VerticalBarChart(data=data)
d5 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED), ("E", 40, RED), ]
chart = VerticalBarChart(data=d5)
여러 가지 파라미터 지정해서 바 차트 만들기
CONFIG에 있는 모든 파라미터의 지정이 가능합니다.
CONFIG = {
"is_add_bars": False, # False: not add, later want to do animation
"title": "Bar Chart", # or None
"title_color": WHITE,
"title_size": 0.6,
"title_buff": 0.5,
"title_font": None,
"x_axis_length": 10,
"x_min":0,
"x_max":100,
"x_axis_title": 'X values',
"x_axis_title_color": WHITE,
"x_axis_title_size": 0.4,
"x_axis_title_buff": 0.2,
"y_axis_title": 'Y values',
"y_axis_title_color": WHITE,
"y_axis_title_size": 0.4,
"y_axis_title_buff": 0.2,
"y_min": 0,
"y_max": 100,
"y_tick_frequency": 20,
"y_axis_length": 5,
"y_labels_color": WHITE,
"y_labels_size": 0.3,
"y_labels_buff": 0.2,
"y_labels_decimal_places": 0,
"graph_origin": np.array([-5,-2, 0]),
"bar_names": ["A", "B", "C", "D", "E"],
"bar_names_color": WHITE,
"bar_names_buff": 0.2,
"bar_names_size": 0.3,
"bar_values": [30, 50, 80, 60, 40],
"bar_values_position": UP, # UP: above the bar, DOWN: below the bar
"bar_values_buff": 0.3, #buff to the bar edge
"gap_ratio": 0.2, # gap ratio with the rectangle's width -> gap_width / rect_width
"edge_buff": 0.5, # for the space between x_axis's start and first rectangle, last rect and the end
"bar_colors": [RED, RED, RED, RED, RED],
"bar_fill_opacity": 1.0,
"bar_stroke_width": 0,
}
지정 방법은,
bar_chart = VerticalBarChart(
data=data,
graph_origin=np.array([-5.5, -2, 0]),
x_axis_length=6.5, y_axis_length=4.5,
bar_names_size=0.25,
title=None,
is_add_bars=is_add_bars,
gap_ratio=gap_ratio,
bar_values_position=bar_values_position,
)
샘플 예제
여러 가지 파라미터를 지정하면서 바 차트를 만들어본 예제입니다.
여기 있는 코드들을 참조하면 가능한 대부분의 VerticalBarChart 사용법을 알 수 있을 것입니다.
위 동영상에 대한 소스 코드는,
#plottest.py
from manimlib.imports import *
from src.comp.plot import VerticalBarChart
class VerticalBarChartTest(Scene):
CONFIG = {
"camera_config": {"background_color": DARKER_GREY},
# "camera_config": {"background_image": "C:\\now\manim\\res\\grey_background.png"},
}
def construct(self):
self.introduction()
self.one_chart_from_data()
self.two_several_data()
self.three_bar_width()
self.four_bar_color()
self.five_animation()
self.six_bar_values()
self.seven_shrink_move()
self.the_end()
def get_text(self, str, color=WHITE, size=0.25):
return Text(str, font='맑은 고딕', stroke_width=0, color=color, size=size)
def get_title_texts(self, *str):
texts = VGroup(*[self.get_text(s, color=YELLOW) for s in str])
texts.arrange(DOWN, aligned_edge=LEFT)
texts.shift(RIGHT*4).to_edge(UP, buff=1.5)
return texts
def get_chart(self, data, is_add_bars=False, gap_ratio=0.2, bar_values_position=UP,):
bar_chart = VerticalBarChart(
data=data,
graph_origin=np.array([-5.5, -2, 0]),
x_axis_length=6.5, y_axis_length=4.5,
bar_names_size=0.25,
title=None,
is_add_bars=is_add_bars,
gap_ratio=gap_ratio,
bar_values_position=bar_values_position,
)
return bar_chart
def introduction(self):
t1 = self.get_text("Introduction to VerticalBarPloat in manim", size=0.4)
t2 = self.get_text("by Heejin", size=0.3)
title = VGroup(t1, t2)
title.arrange(DOWN).to_edge(UP, buff=1)
self.play(FadeInFrom(title, UP), run_time=2)
self.wait()
self.play(FadeOut(title))
def one_chart_from_data(self):
t1 = "HorizontalBarChart shows Bar Chart"
t2 = "using the given data of turple"
title = self.get_title_texts(t1, t2)
s1 = self.get_text(r"data = [")
s2 = self.get_text(r"('Mullet',30,RED),('Mackerel',50,RED),")
s3 = self.get_text(r"('Salmon',80,RED),('Shark',60,RED),")
s4 = self.get_text(r"('Whale',40,RED),")
s5 = self.get_text(r"]")
s6 = self.get_text(r"chart = VerticalBarChart(data)")
ss = VGroup(s1,s2,s3,s4,s5,s6)
ss.arrange(DOWN, aligned_edge=LEFT)
s2.shift(RIGHT*0.2)
s3.shift(RIGHT * 0.2)
s4.shift(RIGHT * 0.2)
ss.next_to(title, DOWN, buff=1)
data = [
("Mullet", 30, RED), ("Mackerel", 50, RED),
("Salmon", 80, RED), ("Shark", 60, RED),
("Whale", 40, RED),
]
bar_chart = VerticalBarChart(data,
graph_origin = np.array([-5.5,-2,0]),
x_axis_length=6.5, y_axis_length=4.5,
bar_names_size=0.25,
title=None,
is_add_bars=False, )
bar_animation = bar_chart.get_bar_animation()
self.play(LaggedStart(
ShowCreation(title),
ShowCreation(ss),
FadeIn(bar_chart),
bar_animation,
))
self.wait(3)
self.play(
FadeOut(title),
FadeOut(ss),
FadeOut(bar_chart),
)
bar_chart.fadeout_bars(self)
self.wait()
def two_several_data(self):
t1 = "Number of bars changes automatically "
t2 = "according to the given data number"
title = self.get_title_texts(t1, t2)
s1 = self.get_text("The number of data:")
decimal = DecimalNumber(2, num_decimal_places=0 )
s1.next_to(title, DOWN, aligned_edge=LEFT, buff=1)
decimal.next_to(s1, RIGHT)
d2 = [("A", 30, RED), ("B", 50, RED),]
d3 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ]
d4 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED),]
d5 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED),("E", 40, RED), ]
d6 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED),("E", 40, RED),("F", 20, RED), ]
d7 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED),("E", 40, RED),("F", 20, RED),("G", 70, RED), ]
d8 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED),("E", 40, RED),("F", 20, RED),("G", 70, RED),("H", 50, RED), ]
data = [d2, d3, d4, d5, d6, d7, d8, ]
charts = [self.get_chart(d, is_add_bars=True) for d in data]
self.play(
ShowCreation(title),
ShowCreation(s1),
ShowCreation(decimal),
FadeInFromDown(charts[0]),
)
for i in range(1,7):
self.play(
decimal.set_value, i+2,
ReplacementTransform(charts[i-1], charts[i], run_time=1.5),
)
self.wait(2)
self.play(
FadeOut(title),
FadeOut(s1),
FadeOut(decimal),
FadeOut(charts[6]),
)
def three_bar_width(self):
t1 = "Bar's width can be changed "
t2 = "with the ratio of the width and gap "
t3 = "between the bars "
title = self.get_title_texts(t1, t2, t3)
s1 = self.get_text("gap_ratio:")
decimal = DecimalNumber(0.1, num_decimal_places=1)
s1.next_to(title, DOWN, aligned_edge=LEFT, buff=1)
decimal.next_to(s1, RIGHT)
d5 = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED), ("E", 40, RED), ]
chart = self.get_chart(d5, is_add_bars=True, gap_ratio=0.1)
self.play(
FadeInFrom(chart),
ShowCreation(title),
FadeIn(s1),
FadeIn(decimal),
run_time=2,
)
vt = ValueTracker(1, num_decimal_places=1)
def update_func(mob):
new_chart = self.get_chart(d5, is_add_bars=True, gap_ratio=vt.get_value()/10)
chart.become(new_chart)
chart.add_updater(update_func)
decimal.add_updater(lambda m: m.set_value(vt.get_value()/10))
self.play(
vt.set_value, 15,
run_time=12,
rate_func=there_and_back,
)
self.wait(2)
self.play(
FadeOut(title),
FadeOut(s1),
FadeOut(decimal),
FadeOut(chart),
)
def four_bar_color(self):
t1 = "Bar's color can be changed "
t2 = "at once or it can be changed "
t3 = "one by one. "
title = self.get_title_texts(t1, t2, t3)
s1 = self.get_text("color:")
color_strs = ["RED","ORANGE","YELLOW","GREEN","BLUE","PURPLE","different one by one", "different one by one"]
color_texts= VGroup(*[self.get_text(str) for str in color_strs])
s1.next_to(title, DOWN, aligned_edge=LEFT, buff=1)
color_texts.next_to(s1, RIGHT)
d_red = [("A", 30, RED), ("B", 50, RED), ("C", 80, RED), ("D", 60, RED), ("E", 40, RED), ]
d_orange = [("A", 30, ORANGE), ("B", 50, ORANGE), ("C", 80, ORANGE), ("D", 60, ORANGE), ("E", 40, ORANGE), ]
d_yellow = [("A", 30, YELLOW), ("B", 50, YELLOW), ("C", 80, YELLOW), ("D", 60, YELLOW), ("E", 40, YELLOW), ]
d_green = [("A", 30, GREEN), ("B", 50, GREEN), ("C", 80, GREEN), ("D", 60, GREEN), ("E", 40, GREEN), ]
d_blue = [("A", 30, BLUE), ("B", 50, BLUE), ("C", 80, BLUE), ("D", 60, BLUE), ("E", 40, BLUE), ]
d_purple = [("A", 30, PURPLE), ("B", 50, PURPLE), ("C", 80, PURPLE), ("D", 60, PURPLE), ("E", 40, PURPLE), ]
d_rainbow1 = [("A", 30, RED), ("B", 50, ORANGE), ("C", 80, YELLOW), ("D", 60, GREEN), ("E", 40, BLUE), ]
d_rainbow2 = [("A", 30, BLUE), ("B", 50, GREEN), ("C", 80, GREY), ("D", 60, RED), ("E", 40, ORANGE), ]
data = [d_red, d_orange, d_yellow, d_green, d_blue, d_purple, d_rainbow1, d_rainbow2 ]
charts = [self.get_chart(d, is_add_bars=True) for d in data]
self.play(
FadeInFrom(charts[0]),
ShowCreation(title),
FadeIn(s1),
FadeIn(color_texts[0]),
run_time=2,
)
n = len(charts)
for i in range(1, n):
self.play(
ReplacementTransform(color_texts[i-1], color_texts[i], run_time=1),
ReplacementTransform(charts[i - 1], charts[i], run_time=1.5),
)
self.wait(2)
self.play(
FadeOut(title),
FadeOut(s1),
FadeOut(color_texts[n-1]),
FadeOut(charts[n-1]),
)
def five_animation(self):
t1 = "Supports all animations for entire chart. "
t2 = "Additionally there are two animations "
t3 = "especially for the bars. "
t4 = "(1) GrowFromEdgePoint "
t5 = "(2) GrowFromBottomLine "
title = self.get_title_texts(t1, t2, t3, t4, t5)
s1 = self.get_text("animation:")
ani_strs = ["GrowFromEdgePoint","GrowFromBottomLine"]
ani_texts= VGroup(*[self.get_text(str, color=RED) for str in ani_strs])
s1.next_to(title, DOWN, aligned_edge=LEFT, buff=1)
ani_texts.next_to(s1, RIGHT)
data = [
("Mullet", 30, RED), ("Mackerel", 50, RED),
("Salmon", 80, RED), ("Shark", 60, RED), ("Whale", 40, RED),
]
chart1 = self.get_chart(data)
self.play(
ShowCreation(title),
FadeInFromDown(chart1, run_time=3)
)
self.wait(2)
ani1 = chart1.get_bar_animation(ani_type='GrowFromEdgePoint')
self.play(
FadeIn(s1),
ShowCreation(ani_texts[0]),
ani1,
)
self.play(ani1)
self.wait()
chart1.remove_bars(self)
#ani2
ani2 = chart1.get_bar_animation()
self.play(
ReplacementTransform(ani_texts[0], ani_texts[1]),
ani2,
)
self.play(ani2)
self.wait(2)
chart1.fadeout_bars(self)
self.play(
FadeOut(title),
FadeOut(s1),
FadeOut(ani_texts[1]),
FadeOut(chart1),
)
def six_bar_values(self):
t1 = "The number value of bars "
t2 = "can be displayed over the bar "
t3 = "or inside bar. "
title = self.get_title_texts(t1, t2, t3)
s1 = self.get_text("bar_values_position:")
pos_strs = ["UP","DOWN"]
pos_texts= VGroup(*[self.get_text(str, color=RED) for str in pos_strs])
s1.next_to(title, DOWN, aligned_edge=LEFT, buff=1)
pos_texts.next_to(s1, RIGHT)
data = [
("Mullet", 30, RED), ("Mackerel", 50, RED),
("Salmon", 80, RED), ("Shark", 60, RED), ("Whale", 40, RED),
]
chart1 = self.get_chart(data, is_add_bars=False)
chart2 = self.get_chart(data, is_add_bars=False, bar_values_position=DOWN)
self.play(
ShowCreation(title),
FadeInFromDown(chart1, run_time=3)
)
self.wait(2)
ani1 = chart1.get_bar_animation()
self.play(
FadeIn(s1),
ShowCreation(pos_texts[0]),
ani1,
)
self.play(ani1)
self.wait()
chart1.remove_bars(self)
self.remove(chart1)
self.add(chart2)
#ani2
ani2 = chart2.get_bar_animation()
self.play(
ReplacementTransform(pos_texts[0], pos_texts[1]),
ani2,
)
self.play(ani2)
self.wait(2)
chart2.fadeout_bars(self)
self.play(
FadeOut(title),
FadeOut(s1),
FadeOut(pos_texts[1]),
FadeOut(chart2),
)
def seven_shrink_move(self):
t1 = "Because VerticalBarChart class inherits VGroup, "
t2 = "it can be scaled and moved as a Mobject. "
title = self.get_title_texts(t1, t2)
data = [
("Mullet", 30, RED), ("Mackerel", 50, RED),
("Salmon", 80, RED), ("Shark", 60, RED), ("Whale", 40, RED),
]
chart = self.get_chart(data, is_add_bars=True)
chart.save_state()
self.play(
ShowCreation(title),
FadeInFromDown(chart, run_time=2)
)
self.wait(2)
#1. scale
vt = ValueTracker(0)
chart.add_updater(lambda m: m.scale((10-vt.get_value())/10))
self.play(
vt.set_value, 7,
rate_func=there_and_back,
run_time=4,
)
chart.restore()
#2. rotation
chart.scale(0.5)
self.play(
chart.rotate, 150*DEGREES,
rate_func=there_and_back,
run_time = 5,
)
#3. move
self.play(chart.to_edge, LEFT,)
path = ArcBetweenPoints(LEFT * 4 + UP * 1.5, RIGHT * 4 + DOWN * 2, angle=PI / 2, stroke_width=8)
self.play(MoveAlongPath(chart, path), rate_func=there_and_back, run_time=6)
chart.restore()
self.wait(2)
self.play(
FadeOut(title),
FadeOut(chart),
)
def the_end(self):
t1 = self.get_text("Introduction to VerticalBarPloat in manim", size=0.4)
t2 = self.get_text("by Heejin", size=0.3)
title = VGroup(t1, t2)
s = self.get_text("- The End - ", size=0.6)
title.arrange(DOWN).to_edge(UP, buff=1)
self.play(FadeInFrom(title, UP), run_time=1)
self.wait()
self.play(FadeIn(s), run_time=3)
self.wait(2)
-끝-
반응형
'Programming > Manim Project' 카테고리의 다른 글
원 위의 점이 돌면서 사인/코사인 곡선 그리기 (0) | 2020.09.15 |
---|---|
원 위의 점이 이동하면서 사인 곡선 그리기 (1) | 2020.09.14 |
python의 for 루프 설명하기 (0) | 2020.05.31 |
[컴포넌트]VerticalBarChart 만들기 (2. 핵심코드 설명) (0) | 2020.05.16 |
[컴포넌트]VerticalBarChart 만들기 (1. 설계/소스) (0) | 2020.05.16 |