diff --git a/manim/mobject/types/vectorized_mobject.py b/manim/mobject/types/vectorized_mobject.py index 4e8c268871..a8d32682fd 100644 --- a/manim/mobject/types/vectorized_mobject.py +++ b/manim/mobject/types/vectorized_mobject.py @@ -481,6 +481,64 @@ def set_opacity(self, opacity: float, family: bool = True) -> Self: self.set_stroke(opacity=opacity, family=family, background=True) return self + def scale(self, scale_factor: float, scale_stroke: bool = False, **kwargs) -> Self: + r"""Scale the size by a factor. + + Default behavior is to scale about the center of the vmobject. + + Parameters + ---------- + scale_factor + The scaling factor :math:`\alpha`. If :math:`0 < |\alpha| < 1`, the mobject + will shrink, and for :math:`|\alpha| > 1` it will grow. Furthermore, + if :math:`\alpha < 0`, the mobject is also flipped. + scale_stroke + Boolean determining if the object's outline is scaled when the object is scaled. + If enabled, and object with 2px outline is scaled by a factor of .5, it will have an outline of 1px. + kwargs + Additional keyword arguments passed to + :meth:`~.Mobject.scale`. + + Returns + ------- + :class:`VMobject` + ``self`` + + Examples + -------- + + .. manim:: MobjectScaleExample + :save_last_frame: + + class MobjectScaleExample(Scene): + def construct(self): + c1 = Circle(1, RED).set_x(-1) + c2 = Circle(1, GREEN).set_x(1) + + vg = VGroup(c1, c2) + vg.set_stroke(width=50) + self.add(vg) + + self.play( + c1.animate.scale(.25), + c2.animate.scale(.25, + scale_stroke=True) + ) + + See also + -------- + :meth:`move_to` + + """ + if scale_stroke: + self.set_stroke(width=abs(scale_factor) * self.get_stroke_width()) + self.set_stroke( + width=abs(scale_factor) * self.get_stroke_width(background=True), + background=True, + ) + super().scale(scale_factor, **kwargs) + return self + def fade(self, darkness: float = 0.5, family: bool = True) -> Self: factor = 1.0 - darkness self.set_fill(opacity=factor * self.get_fill_opacity(), family=False) diff --git a/tests/module/mobject/types/vectorized_mobject/test_stroke.py b/tests/module/mobject/types/vectorized_mobject/test_stroke.py index 1110db14b8..25c09cd294 100644 --- a/tests/module/mobject/types/vectorized_mobject/test_stroke.py +++ b/tests/module/mobject/types/vectorized_mobject/test_stroke.py @@ -39,3 +39,25 @@ def test_streamline_attributes_for_single_color(): ) assert vector_field[0].stroke_width == 1.0 assert vector_field[0].stroke_opacity == 0.2 + + +def test_stroke_scale(): + a = VMobject() + b = VMobject() + a.set_stroke(width=50) + b.set_stroke(width=50) + a.scale(0.5) + b.scale(0.5, scale_stroke=True) + assert a.get_stroke_width() == 50 + assert b.get_stroke_width() == 25 + + +def test_background_stroke_scale(): + a = VMobject() + b = VMobject() + a.set_stroke(width=50, background=True) + b.set_stroke(width=50, background=True) + a.scale(0.5) + b.scale(0.5, scale_stroke=True) + assert a.get_stroke_width(background=True) == 50 + assert b.get_stroke_width(background=True) == 25