| from manim import * | |
| class Bezier(VGroup): | |
| def __init__(self, start, handle1, handle2, end, **kwargs): | |
| super().__init__(**kwargs) | |
| self.curve = VMobject(stroke_color=ORANGE,stroke_width=4) | |
| self.start = Circle(arc_center=start, color=RED, radius=0.08, fill_opacity=0.7) | |
| self.end = Circle(arc_center=end, color=BLUE, radius=0.08, fill_opacity=0.7) | |
| self.handle1 = Circle(arc_center=handle1, color=RED, radius=0.05, fill_opacity=0.0) | |
| self.handle2 = Circle(arc_center=handle2, color=BLUE, radius=0.05, fill_opacity=0.0) | |
| self.hline1 = VMobject() | |
| self.hline2 = VMobject() | |
| self.add( | |
| self.curve, | |
| self.start, | |
| self.handle1, | |
| self.handle2, | |
| self.end, | |
| self.hline1, | |
| self.hline2 | |
| ) | |
| self.add_updater(self.updater,call_updater=True) | |
| def updater(self, grp): | |
| start = grp.start.get_center() | |
| handle1 = grp.handle1.get_center() | |
| handle2 = grp.handle2.get_center() | |
| end = grp.end.get_center() | |
| grp.curve.set_anchors_and_handles(anchors1=start, handles1=handle1,handles2=handle2, anchors2=end) | |
| grp.hline1.become(always_redraw(lambda: Line(self.start.get_center(),self.handle1.get_center(), stroke_color=RED,stroke_width=2))) | |
| grp.hline2.become(always_redraw(lambda: Line(self.end.get_center(),self.handle2.get_center(), stroke_color=BLUE,stroke_width=2))) | |
| class bezierex2(Scene): | |
| def construct(self): | |
| path = VMobject(stroke_width=0.3).set_points_as_corners( | |
| [ | |
| [-6,3,0],[-2,2,0],[2,-3,0],[6,0,0],[3,2,0],[-3,-3,0],[-6,0,0] | |
| ] | |
| ).make_smooth() | |
| self.add(path) | |
| bz = Bezier(2*LEFT,LEFT,RIGHT,2*RIGHT) | |
| bz.a = ValueTracker(0.21) | |
| def bz_updater(mobj): | |
| mobj.start.move_to(path.point_from_proportion(mobj.a.get_value())) | |
| mobj.end.move_to(path.point_from_proportion(mobj.a.get_value()-0.1)) | |
| mobj.handle1.move_to(TangentLine(path, mobj.a.get_value(), length=2, d_alpha=1e-6).get_start()) | |
| mobj.handle2.move_to(TangentLine(path, mobj.a.get_value()-0.1, length=2, d_alpha=1e-6).get_end()) | |
| mobj.updater(mobj) | |
| bz.add_updater(bz_updater, call_updater=True) | |
| bz2 = bz.copy() | |
| bz2.a.set_value(0.11) | |
| bz2.update() | |
| self.add(bz,bz2) | |
| self.wait() | |
| self.play( | |
| LaggedStart( | |
| bz.a.animate(rate_func=rate_functions.linear).set_value(1-0.05), | |
| bz2.a.animate(rate_func=rate_functions.linear).set_value(0.9-0.05), | |
| lag_ratio=0.3, | |
| ), | |
| run_time=5, | |
| ) | |
| self.play( | |
| bz.a.animate.set_value(1), | |
| bz2.a.animate.set_value(0.9), | |
| run_time=1, | |
| rate_func=rate_functions.linear | |
| ) | |
| self.wait() |