SVG from Zero to Senior · Part 21 — Choreographing a Scene with SMIL
Part 21 opens a bonus Motion & Scenes arc: direct a whole scene, not one element. Use SMIL syncbase timing (begin="other.end") to sequence sky, sun, clouds and title into a self-playing, looping scene — no JS clock. With a live demo.
Bạn đã xong hai mươi phần cốt lõi — bạn là senior. Phần này mở một nhánh bonus Motion & Scenes. Ở Phần 6 bạn animate một phần tử đơn. Một hoạt cảnh thì khác: nhiều phần tử chuyển động theo một trình tự có chủ ý, như đạo diễn hô khẩu lệnh. Điều đẹp của SMIL là SVG có thể tự dàn dựng chính nó — không cần timeline JavaScript.
Bấm Replay và xem các khẩu lệnh nổ theo thứ tự: trời sáng → mặt trời mọc → mây trôi → tiêu đề hiện → lặp lại.
Mở demo đầy đủ:
Ý tưởng cốt lõi: định thời syncbase
Đa số đặt begin theo giờ đồng hồ — begin="2s". Cái đó dễ vỡ: đổi một thời lượng là phải tự tính lại mọi con số sau đó. Nước đi senior là định thời syncbase — bắt đầu tương đối với vòng đời của animation khác:
<animate id="a_sky" attributeName="opacity" from="0.35" to="1"
begin="0s" dur="1.4s" fill="freeze"/>
<!-- starts the instant the sky animation ENDS -->
<animate id="a_sun" attributeName="cy" from="178" to="96"
begin="a_sky.end" dur="1.6s" fill="freeze"/>
begin="a_sky.end" nghĩa là “bắt đầu khi a_sky xong.” Bạn có thể lệch (a_sun.end+0.3s), móc vào begin thay vì end, hay kích bằng sự kiện. Đổi dur của mặt trời thì mây và tiêu đề tự dời theo — timeline khai báo và tự chữa lành.
fill="freeze" — giữ khung cuối
Mặc định animation SMIL bật về giá trị gốc khi kết thúc — chí mạng cho một cảnh dựng dần. fill="freeze" giữ trạng thái cuối để mỗi khẩu lệnh đã xong ở lại sân khấu khi cái kế tiếp diễn.
Easing trong SMIL: keySplines
SMIL tuyến tính trừ khi bạn bảo khác. Đặt calcMode="spline" và cho một đường Bézier bậc ba mỗi đoạn — cùng toán easing từ các phần CSS:
<animate attributeName="cy" from="178" to="96" dur="1.6s" fill="freeze"
calcMode="spline" keyTimes="0;1" keySplines="0.2 0.8 0.2 1"/>
keySplines đó là ease-out — mặt trời giảm tốc khi yên vị, thay vì dừng phắt.
Cho cả cảnh lặp lại
Mẹo: đưa kết thúc của khẩu lệnh cuối vào begin của khẩu lệnh đầu như một thời điểm bắt đầu thứ hai.
<animate id="a_sky" begin="0s; a_title.end+1.2s" .../>
Một danh sách begin ngăn cách bằng chấm phẩy cho nhiều thời điểm bắt đầu; cái thứ hai nổ 1.2s sau khi tiêu đề xong, khởi động lại chuỗi — một cảnh tự duy trì.
Điều khiển từ JavaScript khi cần
SMIL phơi bày timeline của tài liệu SVG. Bạn hiếm khi cần JS, nhưng cho nút Replay chỉ một lệnh:
svg.setCurrentTime(0); // rewind the whole timeline → scene replays
// el.beginElement(); // manually fire one animation
// el.endElement(); // cut one short
Lời cảnh báo của sư phụ
fill="freeze"hoặc cảnh của bạn reset. Mọi khẩu lệnh dựng dần cần nó.- Móc vào
.end, đừng cứng hóa giây. - SMIL không được hỗ trợ ở vài ngữ cảnh. Nó vững trong trình duyệt hiện đại cho cảnh khai báo, nhưng chuyển động sản phẩm phức tạp thì dùng thư viện Phần 18.
- Tôn trọng
prefers-reduced-motion. Cho người chọn tắt một “khung cuối” tĩnh.
Thực hành
- Thêm khẩu lệnh thứ 5: một con chim bay ngang sau tiêu đề.
- Định lại thời gian cảnh: nhân đôi
durmặt trời và xác nhận mọi khẩu lệnh sau dịch theo, không sửa gì khác. - Bắt đầu theo sự kiện: đổi
beginđầu thànhclick.
Phần tiếp theo
Bạn dàn được một cảnh theo thời gian. Tiếp theo ta cho mọi thứ di chuyển qua không gian dọc các đường cong bất kỳ. Ở Phần 22 ta làm chủ motion path — animateMotion, <mpath>, và orient="auto" để một vật đi theo con đường, một sao chổi lướt theo cung, và một nhãn cưỡi đường cong mà vẫn hướng đúng.