Fix `Write()` stroke width to scale with `font_size` or object scale
Overview: What does this pull request change?
- Fix #4220
- Add docstring
Motivation and Explanation: Why and how do your changes improve the library?
Previously, the stroke effect was hardcoded and appeared too thick on small fonts and too thin on large ones.
This PR introduces a helper method _adjust_stroke_width_for_text() that dynamically adjusts the stroke width based on the font size of the text, proportionally scaled to 25% of the default stroke width.
The adjustment only applies when:
- The the
font_sizeis too small, such as below20, so zooming-in is needed. - The the
font_sizeis too big, but this is actually not a problem, but scalingstroke_widthmake it look better. - The
stroke_widthis not explicitly provided by the user.
For all other cases, the stroke_width is 2.0 (default from DrawBorderThenFill), and behaves like before this change.
Links to added or changed documentation pages
https://manimce--4222.org.readthedocs.build/en/4222/reference/manim.animation.creation.Write.html
Further Information and Comments
Test:
class WriteScaleStrokeWidth(MovingCameraScene):
def construct(self):
self.add(NumberPlane())
test1 = MathTex(r"\text{MatText Test}").scale(4).set_color(RED)
self.play(Write(test1,run_time=2))
test2 = Text("Text Test").scale(0.1).set_color(BLUE).next_to(test1, DOWN*2)
camera_frame = self.camera.frame
self.play(
camera_frame.animate(rate_func=linear).set(width=test2.width+0.2).move_to(test2)
)
wr = Write(test2,run_time=2)
self.play(wr)
self.wait()
Before the fix:
https://github.com/user-attachments/assets/e3dbbd65-6a90-46e5-b85e-77ef7f2c20ba
After the fix:
https://github.com/user-attachments/assets/9f9bd9a7-84e5-4acf-9885-4f2dd77f3ed6
Reviewer Checklist
- [ ] The PR title is descriptive enough for the changelog, and the PR is labeled correctly
- [ ] If applicable: newly added non-private functions and classes have a docstring including a short summary and a PARAMETERS section
- [ ] If applicable: newly added functions and classes are tested
I'm still not sure why the tests are failing — the code works fine on my local machine. Is there something in my code that I need to change?
Edit:
I've addressed the failed test by scaling stroke_width only if font_size is too small or too large, and the vmobject has a non-zero height.
My investigation:
- Too small in normal Scene appear: the font_size < 20, so zooming-in is needed.
- Too big is actually not a problem, but scaling
stroke_widthmake it look better. - If the mobject height is zero, accessing
font_sizecausesZeroDivisionError.
For other cases, it behaves like before.