Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scale_stroke boolean parameter to VMobject.scale() to allow scaling stroke_width along with the VMobject #3965

Merged
merged 13 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions manim/mobject/types/vectorized_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
22 changes: 22 additions & 0 deletions tests/module/mobject/types/vectorized_mobject/test_stroke.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading