🎬 manim-fa
افزونهی مانیم برای نمایش صحیح متن فارسی (راستبهچپ)، با فونت داخلی، تبدیل فینگلیش به فارسی، و قالببندیِ بولد/ایتالیک/زیرخط/هایلایت.
نصب
pip install -e .
وابستگیها (manim, manimpango) بهصورت خودکار نصب میشوند.
استفادهی سریع
from manim import *
from manim_fa import FaText, fa_write
class Demo(Scene):
def construct(self):
t = FaText("به مانیم فارسی خوش آمدید!", font_size=48, color=BLUE)
self.play(fa_write(t)) # نوشتن از راست به چپ (طبیعی برای فارسی)
self.wait(1)
قالببندیِ درونمتنی (بولد، ایتالیک، زیرخط، هایلایت)
نیازی به دانستنِ کد یا اندیسِ کاراکتر نیست — کافی است داخلِ خودِ متن از این نشانهها استفاده کنید:
| نحو | نتیجه |
|---|---|
**متن** |
بولد |
*متن* |
ایتالیک |
__متن__ |
زیرخطدار |
==متن== |
هایلایت با رنگ پیشفرض (زرد) |
==متن|رنگ== |
هایلایت با رنگ دلخواه، مثل ==نکتهی مهم|orange== یا با کدِ رنگ ==نکته|#FF8800== |
FaText("میتوان **بولد**، *ایتالیک*، ـ زیرخط ـ و ==هایلایت== را باهم ترکیب کرد.")
FaText("رنگ دلخواه: ==نکتهی مهم|orange==")
برای نوشتنِ خودِ نویسههای *، _، = بهصورت عادی (بدون تفسیر بهعنوان
قالببندی)، قبلشان یک بکاسلش بگذارید: \*, \_, \=.
اگر متنِ شما بهطور طبیعی حاویِ این نویسههاست و اصلاً نمیخواهید تفسیر
شوند، از markup=False استفاده کنید:
FaText("۳*۴=۱۲", markup=False)
دقیقتر: markup=False یعنی نشانههای خودِ manim-fa (**, *, __, ==) تفسیر نمیشوند و
متن «همانطور که هست» به Pango داده میشود. پس میتوانید خودتان Pango Markup بنویسید
(مثل <span fgcolor='red'>سدیم</span>، که manim-fa-chemistry برای رنگآمیزیِ نامها استفاده
میکند)، و نویسههای < و & را باید خودتان escape کنید (<، &).
متنِ کاملاً خام: literal=True
اگر متن شامل <، &، **، == یا _ است و میخواهید دقیقاً همانطور که نوشتهاید نمایش داده شود
(فرمول، برچسب، …)، نیازی به escape نیست:
FaText("غلظت < ۳ مولار & برچسب **x** و ==y==", literal=True)
(markup=False فرق دارد: نشانههای manim-fa را تفسیر نمیکند ولی متن را بهعنوان Pango Markup میخواند.)
انیمیشنِ نوشتنِ راستبهچپ با fa_write
متنِ چندخطی خطبهخط نوشته میشود: خطِ اول اول، و هر خط از راست به چپ. در خطهای مخلوط، کلمههای
لاتین و عددها (H2O، ۲۵، 3.14) از چپ به راست نوشته میشوند، مثلِ نوشتنِ دست.
از fa_write(mobject) بهجای Write(mobject) استفاده کنید تا حروف از
راست به چپ (جهتِ طبیعیِ نوشتنِ فارسی) ظاهر شوند — با همان افکتِ اصیلِ
«دستنویسی» (اول خطدورِ حرف کشیده میشود، بعد پر میشود) که خودِ
Write() مانیم دارد؛ چون در پسِ صحنه دقیقاً از همان مکانیزم استفاده
میکند. تنها تفاوتش با Write(reverse=True) این است که با متنِ دارای
هایلایت هم درست کار میکند (جعبهی هایلایت همیشه همراه با متنِ خودش
ظاهر میشود، نه با تاخیر یا جلوتر):
t = FaText("این متن ==هایلایت== و **بولد** دارد.")
self.play(fa_write(t, run_time=3))
🌀 فهرست کامل انیمیشنهای کاربردی در Manim
| نام انیمیشن | کاربرد | مثال |
|---|---|---|
Write() |
نوشتن تدریجی متن | self.play(Write(t)) |
Create() |
رسم کامل یک شیء از ابتدا | self.play(Create(circle)) |
FadeIn() |
ظاهر شدن تدریجی شیء | self.play(FadeIn(t)) |
FadeOut() |
محو شدن تدریجی شیء | self.play(FadeOut(t)) |
FadeToColor() |
تغییر رنگ شیء با انیمیشن نرم | self.play(FadeToColor(t, RED)) |
Transform() |
تبدیل یک شیء به شیء دیگر | self.play(Transform(t1, t2)) |
ReplacementTransform() |
جایگزینی تدریجی یک شیء با دیگری | self.play(ReplacementTransform(t1, t2)) |
Rotate() |
چرخش شیء به اندازه مشخص | self.play(Rotate(t, angle=PI/2)) |
ScaleInPlace() |
بزرگ یا کوچک شدن در محل فعلی | self.play(t.animate.scale(1.5)) |
MoveAlongPath() |
حرکت شیء روی مسیر مشخص | self.play(MoveAlongPath(t, circle)) |
Circumscribe() |
ترسیم حاشیه دور شیء | self.play(Circumscribe(t)) |
GrowFromCenter() |
رشد شیء از مرکز | self.play(GrowFromCenter(t)) |
ShrinkToCenter() |
جمع شدن شیء به مرکز | self.play(ShrinkToCenter(t)) |
Wiggle() |
لرزش یا تکان نرم | self.play(Wiggle(t)) |
FocusOn() |
فوکوس با تغییر نور یا رنگ | self.play(FocusOn(t)) |
Flash() |
درخشش سریع در محل شیء | self.play(Flash(t)) |
Indicate() |
نمایش تأکید با رنگ و مقیاس | self.play(Indicate(t)) |
ApplyWave() |
حرکت موجی روی شیء | self.play(ApplyWave(t)) |
ApplyMethod() |
اجرای متد خاص روی شیء | self.play(ApplyMethod(t.shift, UP)) |
animate.shift() |
جابهجایی شیء | self.play(t.animate.shift(UP)) |
animate.set_color() |
تغییر رنگ شیء | self.play(t.animate.set_color(BLUE)) |
animate.rotate() |
چرخش با انیمیشن نرم | self.play(t.animate.rotate(PI/3)) |
سایر امکانات
متن ترکیبی (فارسی + انگلیسی + عدد)
FaText("این متن ترکیبی است: Hello 123 پایان.")
تبدیل فینگلیش به فارسی
FaText("Salam be Manim, khosh amadid", translit=True) # سلام به مانیم، خوش آمدید
FaText("khoone", translit=True, translit_words={"khoone": "خانه"}) # فرهنگِ دلخواهِ خودتان
⚠️ توجه: این تبدیل تقریبی است، نه آوانگاری زبانشناختیِ کامل. برای کلمههای پرکاربرد (salam، khoda،
be، dar، agar، …) یک فرهنگِ کوچکِ داخلی هست و «e» پایانیِ پس از همخوان به «ه» تبدیل میشود
(khane ← «خانه»)؛ کلمههای دیگر حرفبهحرف تبدیل میشوند (مثلاً «kitab» ← «کیتاب» نه «کتاب»).
برای کلمههای مهم، خودتان با translit_words املا را تعیین کنید و خروجی را بازبینی کنید.
فقط «متن» تبدیل میشود، نه نشانههای قالببندی و نه نامِ رنگِ هایلایت.
جهتِ جملههای فارسی که با حرفِ لاتین شروع میشوند
FaText("pH محلول برابر ۷ است.")
FaText("H2O یک مولکول است.")
Pango جهتِ هر خط را از اولین حرفِ «قوی» میگیرد؛ بنابراین چنین جملهای چپبهراست چیده میشد
(«pH» سمتِ چپ و نقطه سمتِ راست). manim-fa برای خطهایی که فارسیمحورند ولی با حرفِ لاتین شروع
میشوند یک نشانهٔ نامرئیِ راستبهچپ میگذارد تا درست چیده شوند. rtl=False این را خاموش میکند.
فونت دلخواه
FaText("سلام", font="IRTitr") # اگر روی سیستم نصب باشد استفاده میشود
FaText("سلام") # وگرنه از فونت داخلی «وزیرمتن» استفاده میشود
عیبیابی
فونتِ متن اشتباه است (شبیه وزیرمتن نیست)
اگر با نسخههای قدیمیِ manim-fa (پیش از ۱٫۲٫۰) ویدیو ساختهاید، مانیم متنِ اشتباه را در پوشهٔ
media/texts نگه داشته و دوباره میخواند. یکبار پاکش کنید:
import manim_fa
manim_fa.clear_text_cache()
(یا پوشهٔ media/texts را دستی پاک کنید.)
ترتیبِ import
از نسخهٔ ۱٫۲٫۰ ترتیبِ import مهم نیست. (نسخههای قبلی اگر پلاگینی مثل manim-fa-chemistry نصب
بود و اولین import برنامه import manim_fa بود، با ImportError … partially initialized module
میشکستند.)
فونت همراه پلاگین
فونت وزیرمتن (Vazirmatn) با
مجوز SIL Open Font License 1.1 همراه پلاگین توزیع میشود
(manim_fa/fonts_data/، مجوز در همان پوشه در OFL.txt). این یک فونت
مدرن با پشتیبانیِ کامل OpenType برای اتصالِ حروفِ فارسی/عربی است.
معماریِ فنی (برای مشارکتکنندگان)
manim_fa/text.py— تابعِFaText: تبدیل فینگلیش (اختیاری) ← تفسیرِ نشانههای قالببندی به Pango Markup ← ساختِMarkupTextبا فونتِ تضمینشده.manim_fa/markup.py— پارسرِ نحوِ ساده (**,*,__,==) به Pango Markup، با escape کردنِ نویسههای XML و پشتیبانی از بکاسلشبراینویسهیخام.manim_fa/fonts.py— ثبتِ فونتِ داخلی نزد Pango/ManimPango هنگامِ import (نه اولینFaText؛ ثبتِ دیرهنگام بیاثر است) و انتخابِ بهترین فونتِ در دسترس.manim_fa/cache.py—clear_text_cache(): پاککردنِ کشِ متنِ مانیم.
نکتهٔ طراحی: manim_fa هنگامِ import هیچچیز از manim وارد نمیکند (فقط موقعِ استفاده). مانیم هنگامِ
بالا آمدن پلاگینهای ثبتشده را بارگذاری میکند و آنها from manim_fa import FaText میزنند؛ اگر manim_fa
خودش هنگامِ import سراغِ manim میرفت، ترتیبِ import میتوانست آن را بشکند.
manim_fa/translit.py— تبدیلِ قاعدهمبنایِ فینگلیش به فارسی.manim_fa/animation.py— تابعِfa_write: نسخهی راستبهچپِWrite()که فقط ترتیبِ سطحِ بالا را برعکس میکند (نه بازگشتی) تا هم افکتِ اصیلِ دستنویسی حفظ شود، هم هایلایتها سالم بمانند.
چرا هیچجا arabic_reshaper/python-bidi استفاده نشده؟
با رندرِ واقعی و بررسیِ OCR ثابت شد که موتور متنِ خودِ مانیم (Pango + HarfBuzz) کاملاً از الگوریتم دوجهتهی یونیکد و اتصالِ حروفِ فارسی/عربی پشتیبانی میکند. اضافهکردنِ این کتابخانهها باعثِ «پردازشِ دوباره» و درنتیجه بههمریختنِ حروف میشود.
چرا fa_write بهجای Write(reverse=True) مستقیم؟
Write(reverse=True) خودِ مانیم از mobject.invert(recursive=True)
استفاده میکند که ترتیبِ همهی سطوحِ تودرتو را برعکس میکند، نه فقط
سطحِ بالا. این باعث میشد بلوکِ ادغامشدهی هایلایت (جعبه + حروفش، که در
FaText عمداً در یک VGroup قرار میگیرند) از داخل هم برعکس شود و جعبه
از متنِ خودش جدا بیفتد. به همین دلیل fa_write از یک زیرکلاسِ کوچک
استفاده میکند که فقط ترتیبِ سطحِ بالا را برعکس میکند (نه بازگشتی)، تا
ترتیبِ داخلیِ هر هایلایت (جعبه، سپس حروفش) همیشه دستنخورده بماند.
اجرای تستها
pip install pytest
pytest tests/
مثالها
پوشهی examples/ شامل چند صحنهی نمونه است:
cd examples
manim -pql demo.py Demo
manim -pql demo_formatting.py FormattingShowcase
manim -pql demo_comparison.py Comparison
محدودیتهای شناختهشده
translit_to_faیک تبدیلِ تقریبی است (بالا توضیح داده شد).- نشانههای قالببندی (
**,*,__,==) با هم تودرتو پشتیبانی نمیشوند (مثلاً بولدِ ایتالیک). - ترکیبِ چند عبارتِ لاتین/عددیِ متوالی داخلِ یک جملهی فارسی، طبقِ خودِ الگوریتمِ دوجهتهی یونیکد میتواند رفتارِ ظریفی داشته باشد. (جملههایی که با حرفِ لاتین شروع میشوند از نسخهٔ ۱٫۲٫۰ درست چیده میشوند؛ بالا ببینید.)
- ترتیبِ نوشتنِ
fa_writeبرای خطهای مخلوط بر اساسِ تطبیقِ «حرف با نویسه» است. اگر تطبیق ممکن نباشد (مثلاً برخی عبارتهای عربی با لیگاتورهای خاص)، همان راستبهچپِ ساده بهکار میرود. - در
literal=True، جای نشانههای خنثی (*،=) کنارِ حرفِ لاتین طبقِ الگوریتمِ دوجهتهٔ یونیکد ممکن است جابهجا دیده شود.
سازگاری
با Manim Community v0.18.1، v0.19.0 و v0.21.0 و ManimPango 0.6.1 (روی لینوکس، Python 3.12) با رندرِ واقعی تست شده است. ۲۷۵ تستِ غیرشبکهایِ manim-fa-chemistry هم با آن میگذرد. (ویندوز و مک آزمایش نشدهاند.)
مجوز
این پروژه تحت مجوز MIT منتشر میشود. ساختهشده توسط علی تابش برای جامعهی فارسیزبانِ Manim.
🤝 مشارکت
Pull Request یا Issue خوشآمد است.
Release files for manim-fa 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| manim_fa-1.2.0.tar.gz | 232.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| manim_fa-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 399.2 kB
Release files / manim_fa-1.2.0.tar.gz
| Download URL | manim_fa-1.2.0.tar.gz |
|---|---|
| Size | 232.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
428e3de971277ddcb92305c7504843ce97d48293e8c43558208c125279f17bc7
|
|
BLAKE2b-256 checksum How to use checksums |
76bf39a549be60d48b27698bc0f8a080e7c6a8d8aa2ecea03a3c8cfb785836ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / manim_fa-1.2.0-py3-none-any.whl
| Download URL | manim_fa-1.2.0-py3-none-any.whl |
|---|---|
| Size | 166.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4034903bfa3c4600c3ac11d9ddec94037e73bb143767a021850f90075bf36799
|
|
BLAKE2b-256 checksum How to use checksums |
42eb56738c37839163c11cae65fdfb075df8f7f8dd4e3a998f08dd25aa71d380
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|