SVG feMorphology: Thêm đường viền mà không tạo đường dẫn
Tạo đường viền SVG từ SourceAlpha bằng feMorphology. So sánh giãn, co, lỗ và bán kính không đều mà vẫn giữ nguyên hình học của đường dẫn gốc.
Trên trang này
Để tạo đường viền cho toàn bộ hình bao của một SVG nhiều màu, hãy giãn SourceAlpha, loại bỏ alpha gốc khỏi kết quả lớn hơn đó, tô màu phần vòng còn lại rồi ghép hình gốc lên trên. Bộ lọc thay đổi diện mạo khi hiển thị, còn dữ liệu đường dẫn gốc vẫn giữ nguyên.
Dùng operator="erode" khi bạn muốn thu nhỏ hình bao alpha. Cả hai thao tác đều không tạo ra đường dẫn dịch biên có thể chỉnh sửa. Bạn cần kiểm tra trực quan các lỗ, khe hẹp và góc nhọn vì phép hình thái học dùng vùng lân cận hình chữ nhật, thay vì phép dịch biên đường viền theo hình tròn.
Bắt đầu từ hình bao, không phải các kênh màu
Đặc tả Filter Effects của W3C định nghĩa phép giãn là lấy giá trị lớn nhất theo từng thành phần trong một vùng lân cận hình chữ nhật, còn phép co là lấy giá trị nhỏ nhất. Với SourceAlpha, đầu vào là kênh alpha của hình. Nhờ vậy, chúng ta có thể tạo hình bao mà không giãn riêng các kênh màu xanh mòng két và san hô.
Ví dụ này áp dụng bộ lọc cho toàn bộ hình gồm hai đường dẫn. Lỗ vuông trong suốt là một phần của hình bao alpha. Phần màu san hô đã nằm bên trong vùng xanh mòng két không trong suốt, nên không tạo ra một ranh giới bên ngoài riêng.
Chúng tôi vẽ SVG thủ công rồi mở năm phiên bản độc lập trong trình duyệt. Mọi tệp đều giữ cùng hai định nghĩa đường dẫn gốc. Hình so sánh bên dưới là kết quả hiển thị thực tế của những tệp đó, không dùng hình được đồ lại hay bản xem trước hiệu ứng được tạo bằng AI.

Ở bán kính 10, đường viền nở ra ngoài hình bao nhìn thấy và lấn vào lỗ. Ở 22, màu vàng lấp đầy lỗ vuông của mẫu thử này. Phiên bản 18 4 nở theo chiều ngang nhiều hơn chiều dọc. Phép co thu nhỏ vùng bên ngoài không trong suốt và mở rộng lỗ trong suốt; đỉnh phía dưới cũng thay đổi.
Những quan sát này chỉ áp dụng cho hình và các thiết lập đang dùng. Chúng không phải quy tắc về bán kính an toàn chung cho những logo hay biểu tượng khác.
Tạo vòng alpha bên ngoài
Lưu ví dụ đầy đủ này thành outline.svg rồi mở trong trình duyệt. Đây chính là SVG có bán kính 10 được dùng trong ảnh chụp:
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="220" viewBox="0 0 300 220">
<defs>
<g id="artwork">
<path fill="#173b40" fill-rule="evenodd"
d="M50 60H250V170H170L150 195L130 170H50Z M105 90H145V130H105Z"/>
<path fill="#f28567" d="M175 90H220V140H175Z"/>
</g>
<filter id="outline" filterUnits="userSpaceOnUse"
primitiveUnits="userSpaceOnUse" x="0" y="0" width="300" height="220">
<feMorphology in="SourceAlpha" operator="dilate" radius="10" result="grown"/>
<feComposite in="grown" in2="SourceAlpha" operator="out" result="ring"/>
<feFlood flood-color="#e4b84c" result="paint"/>
<feComposite in="paint" in2="ring" operator="in" result="coloredRing"/>
<feMerge>
<feMergeNode in="coloredRing"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<use href="#artwork" filter="url(#outline)"/>
</svg>Bộ lọc thực hiện bốn bước:
feMorphologygiãnSourceAlphathànhgrown.feCompositegiữ phầngrownnằm ngoài alpha gốc, tạo thànhring.feFloodcung cấp màu vàng; một phép tổng hợp khác giới hạn màu đó trong vòng.feMergeđặtSourceGraphicgốc lên trên vòng đã tô màu.
Thứ tự đầu vào rất quan trọng trong phép trừ. Phần tổng hợp của đặc tả quy định in là nguồn và in2 là đích. Ở đây, in="grown", in2="SourceAlpha" và operator="out" loại vùng không trong suốt gốc khỏi alpha đã giãn. Đảo ngược hai đầu vào này sẽ không tạo ra vòng bên ngoài như trên.
Từ bên ngoài có nghĩa là nằm ngoài vùng alpha không trong suốt, bao gồm cả khoảng trống bên trong lỗ trong suốt. Nếu đường viền phải tránh các lỗ bên trong, bộ lọc này không tự phân biệt điều đó. Bạn cần một hình bao riêng hoặc một cách dựng khác xác định phần ngoài mong muốn.
Màu nguồn vẫn nhìn thấy vì chúng ta ghép SourceGraphic không chỉnh sửa ở bước cuối. Cách này khác với đường viền thông thường của đường dẫn. Để tạo đường viền ở giữa, cắt vào trong hoặc dùng mặt nạ để nằm bên ngoài, xem căn chỉnh đường viền SVG; bài thứ tự tô vẽ giải thích trường hợp đơn giản hơn khi xếp lớp đường viền và màu tô.
Co alpha và giữ lại những màu còn tồn tại
Thay bộ lọc đường viền bằng định nghĩa sau rồi đổi phần use cuối thành filter="url(#erode)":
<filter id="erode" filterUnits="userSpaceOnUse"
primitiveUnits="userSpaceOnUse" x="0" y="0" width="300" height="220">
<feMorphology in="SourceAlpha" operator="erode" radius="10" result="shrunken"/>
<feComposite in="SourceGraphic" in2="shrunken" operator="in"/>
</filter>Phép tổng hợp này chỉ giữ hình gốc ở nơi alpha sau khi co vẫn còn. Nó không ghép lại toàn bộ hình gốc lên trên, vì như vậy sẽ che mất hiệu ứng làm mỏng mong muốn. Trong mẫu thử này, vùng xanh mòng két bên ngoài nhỏ lại, còn vùng san hô vẫn tồn tại bên trong.
Hãy chỉ định rõ toán tử trong các ví dụ thực tế. Tài liệu về operator phân biệt erode và dilate trên feMorphology với in và out trên feComposite. Cùng một tên thuộc tính thực hiện những công việc khác nhau trên hai phần tử. Toán tử mặc định của phép hình thái học là erode, nên bỏ qua nó rất dễ tạo hiệu ứng ngược với phép giãn mà bạn định dùng.
Phân biệt đơn vị bán kính và vùng bộ lọc
Tài liệu về radius cho phép một hoặc hai số. Một số áp dụng cho cả hai trục; nếu có hai số, số đầu là bán kính x và số sau là bán kính y. Với hai trạng thái đường viền bổ sung, chỉ đổi radius="10" thành radius="22" hoặc radius="18 4" trong ví dụ đầy đủ.
Đây là bán kính trong hệ tọa độ được chọn bởi primitiveUnits, không phải cam kết về một đường viền có độ dày cố định theo pixel CSS ở mọi kích thước hiển thị. Chúng tôi dùng rõ ràng primitiveUnits="userSpaceOnUse" với viewBox 0 0 300 220. Khi đổi kích thước SVG hiển thị, hiệu ứng cũng được phóng theo hình.
Hai thuộc tính có tên tương tự điều khiển những yếu tố khác nhau:
| Thuộc tính | Điều khiển | Thiết lập trong ví dụ |
|---|---|---|
| primitiveUnits | Giá trị độ dài bên trong các phần tử bộ lọc, bao gồm bán kính hình thái học | userSpaceOnUse |
| filterUnits | x, y, chiều rộng và chiều cao của vùng bộ lọc | userSpaceOnUse |
| viewBox gốc | Hình chữ nhật tọa độ người dùng được ánh xạ vào khung nhìn SVG | 0 0 300 220 |
Tài liệu primitiveUnits của MDN mô tả hệ tọa độ của các phần tử bộ lọc. Tài liệu filterUnits mô tả riêng vùng bên ngoài. filterUnits mặc định là objectBoundingBox; primitiveUnits mặc định là userSpaceOnUse. Chỉ định rõ cả hai giúp bạn dễ kiểm tra mẫu hơn.
Hình nguồn chiếm từ x=50 đến 250 và từ y=60 đến 195. Bán kính bằng nhau theo hai trục lớn nhất được thử là 22, và vùng bộ lọc cùng khung nhìn 300 × 220 để đủ chỗ cho kết quả đó. Hãy kiểm tra lại cả hai ranh giới khi thay đổi hình hoặc bán kính. Đặc tả mô tả vùng bộ lọc là ranh giới cắt cứng: bán kính lớn hơn cũng không thể vẽ vượt ra khỏi vùng đó. Hướng dẫn về cắt bộ lọc và khung nhìn SVG minh họa hai giới hạn riêng biệt này.
Nếu bộ lọc có vẻ không hoạt động, hãy kiểm tra thêm radius. Giá trị mặc định là 0, và tài liệu cho biết giá trị âm hoặc bằng 0 sẽ vô hiệu hóa hiệu ứng của phần tử bộ lọc. Các ví dụ trên dùng giá trị dương được chỉ định rõ trên cả hai trục.
Kiểm tra lỗ và góc trước khi bàn giao
Vùng lân cận hình chữ nhật của phép hình thái học tạo diện mạo khác với đường viền bo tròn thông thường. Bán kính x và y bằng nhau không biến vùng lân cận đó thành hình tròn. Đỉnh phía dưới có dạng bậc trong hình so sánh là nơi hữu ích để quan sát khác biệt.
| Kết quả | Kiểm tra trước khi sử dụng |
|---|---|
| Đường viền ngoài lớn hơn | Các lỗ và hình lân cận có thể trông như nối liền nhau |
| Hình bao bị co | Chi tiết mảnh có thể biến mất và lỗ có thể lớn hơn |
| Bán kính khác nhau theo hai trục | Mức nở ngang và dọc khác nhau có chủ đích |
| Bản xem trước trong trình duyệt đúng | Trình chỉnh sửa hoặc công cụ xuất đích vẫn cần được thử riêng |
| Cần đường viền dưới dạng hình học có thể chỉnh sửa | Kết quả bộ lọc trực tiếp không phải đường bao mới trong nguồn |
Chúng tôi đã kiểm tra rằng cả năm tệp vẫn có hai đường dẫn nguồn với thuộc tính d giống nhau. Định nghĩa bộ lọc khác nhau; hình học nguồn không thay đổi. Hãy kiểm tra các đối tượng SVG thực tế khi đích đến cần đường dẫn có thể chỉnh sửa, dịch biên hoặc đưa vào sản xuất. Dùng thao tác hình học của trình chỉnh sửa cho yêu cầu đó, rồi kiểm tra các đường bao tạo ra. Chỉ thay đổi hoặc xóa bộ lọc này không cung cấp các đường bao ấy.
Giữ một bản gốc không có bộ lọc và một bản bàn giao riêng. Mở tệp bàn giao trong đích đến thực tế rồi so sánh góc, lỗ bên trong, màu sắc và giới hạn. Ví dụ trong trình duyệt này không xác nhận khả năng hỗ trợ của một ứng dụng thiết kế, công cụ xuất hay máy cắt cụ thể.
Chuẩn bị nguồn trước khi thêm hiệu ứng
PerfectVector có thể giúp khi hình ban đầu chỉ có dạng PNG hoặc JPG. Chuẩn bị một bản SVG để đánh giá, rồi kiểm tra hình bao nguồn đã khôi phục, các lỗ nhỏ và ranh giới màu trước khi áp dụng bộ lọc. Đường viền hình thái học sẽ khuếch đại vấn đề trong hình bao đó, thay vì sửa hình học mong muốn cho bạn.
Hãy dùng trực tiếp bản vector gốc nếu có. Với biểu tượng đơn giản, vẽ lại thủ công có thể dễ kiểm soát hơn. Đồ lại một ảnh đã làm phẳng có đường viền gắn sẵn không khôi phục được thiết lập bộ lọc gốc, cũng không xác định được phần nào là hình trước khi lọc. Tổng quan về vector hóa ảnh giải thích giới hạn của việc tái dựng này.
Câu hỏi thường gặp
feMorphology có tạo đường viền dưới dạng đường dẫn có thể chỉnh sửa không? Không. Nó thay đổi kết quả hiển thị của bộ lọc. Ví dụ này giữ nguyên hai đường dẫn nguồn, nên đích đến cần đường bao riêng phải dùng thao tác hình học và kiểm tra khi nhập.
Vì sao đường viền vàng lấp lỗ trong SVG của tôi? Vòng nở ra ngoài alpha không trong suốt, bao gồm cả vào những lỗ trong suốt. Trong mẫu thử này, bán kính 22 lấp lỗ vuông. Hình khác cần được kiểm tra khe hở và bán kính riêng.
Vì sao dùng SourceAlpha thay vì SourceGraphic? SourceAlpha cho phép bộ lọc xử lý hình bao mà không giãn từng kênh màu gốc. Ví dụ tô màu riêng cho vòng alpha đó rồi ghép SourceGraphic ở bước cuối để hiển thị màu gốc.
Nguồn tham khảo
- W3C — Filter Effects Level 1 — Định nghĩa vùng lân cận hình chữ nhật của phép hình thái học, đầu vào tổng hợp và ranh giới cắt của vùng bộ lọc.
- MDN — radius — Định nghĩa cú pháp bán kính một và hai giá trị, đơn vị và những giá trị vô hiệu hóa hiệu ứng.
- MDN — operator — Phân biệt thao tác hình thái học với thao tác tổng hợp.
- MDN — primitiveUnits — Xác định hệ tọa độ của bán kính hình thái học.
- MDN — filterUnits — Xác định hệ tọa độ của vùng bộ lọc bên ngoài.
Nếu nguồn của bạn chỉ có dạng raster, hãy chuẩn bị hình vector bằng PerfectVector, xác minh hình bao và các lỗ khi chưa có bộ lọc, rồi thêm đường viền và so sánh tệp cuối trong trình xem sẽ tiếp nhận nó.
Thêm từ blog

Nét viền SVG biến mất sau khi xuất: Tìm nguyên nhân
Nét viền SVG có thể biến mất do màu tô, tỷ lệ, giới hạn bằng mặt nạ cắt hoặc hiệu ứng không được hỗ trợ. Kiểm tra đường dẫn trước, rồi áp dụng cách sửa nhỏ nhất đáng tin cậy.

Ảnh SVG trong Graphviz: Giúp hình của nút dễ bàn giao
Thêm hình SVG vào nút Graphviz, kiểm tra tham chiếu ảnh và thử gói tài nguyên đầy đủ với sơ đồ được di chuyển cùng bản bàn giao tự chứa.