Ả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.
Trên trang này
- Phân biệt nút, hình của nút và tham chiếu tệp
- Chạy ví dụ nhỏ với trình kết xuất được chỉ định rõ
- Kiểm tra những gì trình kết xuất ghi ra
- Đóng gói rõ ràng họa tiết đơn giản này
- Tách kích thước và cách co giãn khỏi khả năng bàn giao
- Khôi phục hình ở bước chuẩn bị khi nguồn gốc đã mất
- Câu hỏi thường gặp
- Nguồn tham khảo
Sơ đồ Graphviz có thể chứa nút và mũi tên dạng vector, trong khi hình tùy chỉnh của nút vẫn trỏ đến một tệp ảnh riêng. Nếu hình đó biến mất sau khi bạn di chuyển SVG, hãy kiểm tra tham chiếu ảnh được tạo ra trước khi thay đổi bản vẽ. Phần thiếu có thể nằm trong gói bàn giao.
Trong đầu ra SVG được thử bên dưới, Graphviz giữ motif.svg dưới dạng ảnh liên kết. Gói đầy đủ hiển thị được ảnh; khi chỉ di chuyển sơ đồ, ảnh biến mất. Một bản được đóng gói rõ ràng chứa cả dữ liệu hình và hiển thị trong cùng phép thử trên trình duyệt. Bước đóng gói đó vẫn giữ một phần tử ảnh SVG, thay vì biến họa tiết thành các đường dẫn gốc của đồ thị.
Giữ nguồn DOT để lưu tên nút và các mối quan hệ. Giữ riêng bản gốc của hình, và thử chính đầu ra bạn định dùng trong trình xem hoặc quy trình xuất bản sẽ tiếp nhận nó.
Phân biệt nút, hình của nút và tham chiếu tệp
Thuộc tính image của Graphviz đặt tên hình được hiển thị bên trong một nút. Nó không thay thế danh tính hay các mối quan hệ của nút trong đồ thị. Tài liệu yêu cầu kích thước nguồn; với ảnh SVG, hãy cung cấp width và height rõ ràng với đơn vị phù hợp.
Họa tiết gốc ở đây là bản vẽ hai đường dẫn trong không gian tọa độ 96 × 64. Kích thước bên ngoài là 96pt × 64pt. Nút bao quanh và mũi tên do Graphviz tạo ra.
| Thành phần | Được duy trì trong | Vấn đề có thể xảy ra |
|---|---|---|
| Tên nút, nhãn và cạnh | Nguồn DOT | Mối quan hệ đồ thị hoặc nội dung chữ không đúng |
| Họa tiết tùy chỉnh | Bản SVG gốc của hình | Thiếu kích thước, chi tiết không phù hợp hoặc sai tỷ lệ |
| Liên kết từ sơ đồ đến họa tiết | Tham chiếu ảnh trong SVG xuất ra | Thiếu hình tại đường dẫn sau khi phân giải |
| Vị trí và kích thước cuối | Đầu ra trình kết xuất và trình xem đích | Bị cắt, kéo giãn hoặc có phụ thuộc không được hỗ trợ |
Một phần tử ảnh có thể trỏ đến hình SVG hoặc dữ liệu pixel. Để kiểm tra nguồn raster, dùng bài riêng về chẩn đoán ảnh nhúng trong SVG. Tên tệp kết thúc bằng .svg không đủ để xác định nội dung của bất kỳ tệp nào trong hai tệp.
Chạy ví dụ nhỏ với trình kết xuất được chỉ định rõ
Chúng tôi dùng @viz-js/viz 3.31.0, một bản WebAssembly báo phiên bản Graphviz 16.1.0, với bộ máy bố trí dot và đầu ra SVG tích hợp. Đây là phép thử của bản dựng và trình kết xuất đó, không khẳng định mọi cài đặt Graphviz đều tải ảnh giống nhau.
Trong thư mục dự án Node.js mới, cài gói với phiên bản cố định:
npm install @viz-js/viz@3.31.0Lưu hình gốc thành motif.svg:
<svg xmlns="http://www.w3.org/2000/svg"
width="96pt" height="64pt" viewBox="0 0 96 64">
<path fill="#173b40" fill-rule="evenodd"
d="M48 4C70 4 88 17 88 32S70 60 48 60S8 47 8 32S26 4 48 4Z
M48 14C31 14 19 22 19 32S31 50 48 50S77 42 77 32S65 14 48 14Z"/>
<path fill="#28bfa3"
d="M43 20H53V27H60V37H53V44H43V37H36V27H43Z"/>
</svg>Lưu đồ thị thành diagram.dot:
digraph G {
graph [rankdir=LR, bgcolor="white", margin=0.1];
node [shape=box, fontname="Arial", fontsize=16,
color="#173b40", penwidth=1.5,
fixedsize=true, width=1.8, height=1.1];
artwork [label="", image="motif.svg", imagescale=true];
review [label="Review"];
artwork -> review [color="#173b40", penwidth=1.5];
}Sau đó lưu đoạn này thành render.mjs và chạy node render.mjs từ thư mục đó:
import { instance } from '@viz-js/viz';
import fs from 'node:fs';
const viz = await instance();
const dot = fs.readFileSync('diagram.dot', 'utf8');
const svg = viz.renderString(dot, {
engine: 'dot',
format: 'svg',
images: [{ name: 'motif.svg', width: '96pt', height: '64pt' }]
});
fs.mkdirSync('bundle', { recursive: true });
fs.copyFileSync('motif.svg', 'bundle/motif.svg');
fs.writeFileSync('bundle/diagram.svg', svg);
process.stdout.write(`Graphviz ${viz.graphvizVersion}\n`);Tài liệu API của Viz.js mô tả tùy chọn images là thông tin kích thước ảnh. Cung cấp nó giúp bộ máy bố trí biết về hình có tên này; nó không đưa dữ liệu của tệp vào kết quả. Đơn vị được chỉ định rõ tránh việc coi một số không có đơn vị là pixel CSS. API dùng point cho kích thước không có đơn vị.
Với Graphviz cài đặt trực tiếp, tài liệu image chính thức mô tả tài nguyên ảnh cục bộ và kích thước đọc từ tệp nguồn. Đừng sao chép cách thiết lập siêu dữ liệu của WebAssembly vào lệnh chạy trực tiếp rồi cho rằng nó có cùng cơ chế tải.
Kiểm tra những gì trình kết xuất ghi ra
SVG được tạo của chúng tôi chứa phần tử này:
<image xlink:href="motif.svg"
width="118.8px" height="79.2px"
preserveAspectRatio="xMinYMin meet"
x="5.4" y="-79.2"/>Kích thước và vị trí là những giá trị quan sát được trong mẫu thử này. Phần quyết định cách bàn giao là xlink:href="motif.svg": kết quả vẫn cần tài nguyên ở đường dẫn tương đối đó.
Chỉ sao chép diagram.svg sang thư mục khác, để lại hình ở nơi cũ. So sánh với gói đầy đủ. Chúng tôi phục vụ cả hai thư mục qua HTTP cục bộ và hiển thị mỗi SVG như một tài liệu thông qua phần tử HTML object.

Các khung nút và mũi tên được tạo vẫn hiện khi họa tiết liên kết bị thiếu. Dựng lại bố cục đồ thị không cung cấp tệp đã mất. Khôi phục vị trí tài nguyên được mong đợi, bàn giao cả gói hoặc chọn bước đóng gói phù hợp với đích đến.
Mở SVG như tài liệu và hiển thị nó qua HTML img là hai phép thử khác nhau. Hướng dẫn dùng SVG như ảnh của MDN giải thích rằng ngữ cảnh ảnh có thể hạn chế tài nguyên bên ngoài, còn URL dữ liệu có thể nhúng chúng trực tiếp. Những hạn chế trong ngữ cảnh ảnh được mô tả không áp dụng cho tài liệu SVG trực tiếp hay việc nhúng tài liệu qua object và iframe. Hãy kiểm tra đúng ngữ cảnh bàn giao bạn thực sự dùng.
Đóng gói rõ ràng họa tiết đơn giản này
Với họa tiết gốc tự chứa này, đoạn mã sau thay đúng một tham chiếu đã biết bằng dữ liệu SVG của tệp. Lưu thành package.mjs và chạy sau khi kết xuất:
import fs from 'node:fs';
const svg = fs.readFileSync('bundle/diagram.svg', 'utf8');
const needle = 'xlink:href="motif.svg"';
if (svg.split(needle).length !== 2) {
throw new Error('Expected exactly one motif reference');
}
const data = 'data:image/svg+xml;base64,' +
fs.readFileSync('bundle/motif.svg').toString('base64');
const packaged = svg.replace(needle, `xlink:href="${data}"`);
fs.writeFileSync('self-contained.svg', packaged);Đây là ví dụ đóng gói cho một trường hợp cụ thể, không phải công cụ nhúng SVG tổng quát. Nó xử lý tham chiếu đã biết trong đầu ra này và một họa tiết không có phông chữ, ảnh, biểu định kiểu hay phụ thuộc bên ngoài khác. Hình phức tạp hơn cần được kiểm tra phụ thuộc riêng.
Bản đóng gói hiển thị được họa tiết trong phép thử trình duyệt của chúng tôi. So sánh hai chuỗi đầu ra sau khi che giá trị tham chiếu ảnh cho thấy hình học đồ thị giống nhau. Tệp vẫn chứa một phần tử ảnh; tham chiếu của nó giờ bắt đầu bằng data:image/svg+xml;base64,.
Nhúng dữ liệu ảnh SVG có thể loại bỏ sự phụ thuộc vào đường dẫn tệp này mà vẫn giữ nguồn vector của hình. Nó không biến hình thành dạng nút gốc của Graphviz, thêm điểm kết nối bên trong, hay bảo đảm trình chỉnh sửa khác sẽ cho phép thao tác trực tiếp với các đường dẫn. Hãy thử hành vi nhập của bên nhận.
Cũng đừng nhầm svg_inline với việc nhúng ảnh. Tài liệu đầu ra SVG của Graphviz mô tả nó là đầu ra không có phần đầu để đưa vào HTML. Với cùng đồ thị của chúng tôi, chọn svg_inline vẫn tạo tham chiếu motif.svg. Chế độ đầu ra không đóng gói hình.
Tách kích thước và cách co giãn khỏi khả năng bàn giao
Tài liệu imagescale của Graphviz phân biệt việc đưa ảnh vừa vào nút với kích thước tự nhiên của nguồn. Trong ví dụ này, imagescale=true co giãn đồng đều để ảnh vừa nút. Tùy chọn both co giãn riêng chiều rộng và chiều cao, có thể làm thay đổi tỷ lệ.
Nếu họa tiết hiện nhưng bị kéo giãn, kiểm tra tùy chọn co giãn. Nếu chỉ hiện một phần, kiểm tra giới hạn riêng của nó và không gian nút có sẵn. Nếu nó biến mất sau khi di chuyển tệp, kiểm tra đường dẫn tài nguyên trước. Hướng dẫn kích thước SVG giải thích khác biệt giữa kích thước khai báo và tọa độ bản vẽ.
| Triệu chứng | Kiểm tra trước | Cách sửa nên thử |
|---|---|---|
| Hình biến mất sau khi di chuyển sơ đồ | Tham chiếu ảnh được tạo và vị trí tương đối của tài nguyên | Khôi phục gói hoặc đóng gói rõ ràng nguồn đã thử |
| Bố trí đồ thị chạy được nhưng không có hình | Kích thước nguồn và thiết lập ảnh riêng của bản dựng | Xác nhận tệp và siêu dữ liệu ảnh mà bản dựng đó yêu cầu |
| Họa tiết trông bị kéo giãn | Thiết lập imagescale và tỷ lệ mong muốn | Dùng cách co giãn đồng đều nếu không muốn biến dạng |
| SVG mở trực tiếp được nhưng lỗi trên trang web | Trang dùng ngữ cảnh ảnh hay tài liệu | Thử cách nhúng được hỗ trợ và chính sách tài nguyên của nó |
| Đầu ra khác sau khi đổi trình kết xuất | Trình kết xuất đã chọn và cấu trúc SVG của nó | Kiểm tra lại XML xuất ra và diện mạo cuối |
Trang đầu ra SVG chính thức lưu ý rằng đầu ra Cairo có thể khác đầu ra SVG tích hợp về độ dễ đọc của XML và khả năng biến đổi. Chúng tôi không thử Cairo ở đây. Hãy chỉ định rõ trình kết xuất trong dự án có thể tái lập, và kiểm tra lại bước đóng gói khi thay đổi nó.
Khôi phục hình ở bước chuẩn bị khi nguồn gốc đã mất
PerfectVector có thể giúp khi một họa tiết minh họa phù hợp chỉ còn dưới dạng PNG hoặc bản quét. Quy trình khôi phục hình khoa học cung cấp một bản vector để đánh giá trước khi sử dụng. Cắt ảnh sát họa tiết, kiểm tra hình bao và khoảng trống, rồi xác minh giới hạn và kích thước SVG tải xuống trước khi thêm vào đồ thị.
Việc khôi phục đó không tái dựng mối quan hệ giữa các nút, ý nghĩa mũi tên hay nhãn DOT. Giữ những thông tin đó trong nguồn đồ thị. Dùng SVG gốc nếu có, vẽ lại biểu tượng đơn giản nếu dễ duy trì hơn, và giữ ảnh chụp dưới dạng raster. Tổng quan vector hóa ảnh giải thích giới hạn của việc khôi phục.
Các công cụ sơ đồ khác đóng gói hình tùy chỉnh theo cách khác. Hướng dẫn biểu tượng Mermaid trình bày dữ liệu biểu tượng đã đăng ký, còn bài hình SVG tùy chỉnh trong draw.io phân biệt ảnh nhập vào với khuôn hình gốc. Hãy đưa yêu cầu của đích đến vào quá trình chuẩn bị hình.
Câu hỏi thường gặp
Đầu ra SVG của Graphviz có tự chứa ảnh của nút không? Trong đầu ra SVG tích hợp đã thử, sơ đồ chứa tham chiếu ảnh đến tệp motif.svg riêng. Hãy kiểm tra đầu ra của bạn và bàn giao các phụ thuộc hoặc dùng bước đóng gói đã được thử.
svg_inline có ghép các đường dẫn của ảnh SVG vào đồ thị không? Không. Đây là chế độ đầu ra không có phần đầu để đưa vào HTML. Trong phép thử của chúng tôi, nó giữ tham chiếu motif.svg bên ngoài.
SVG tự chứa có giống hình học nút gốc có thể chỉnh sửa không? Không. Ví dụ đóng gói giữ một phần tử ảnh chứa dữ liệu SVG. Cấu trúc đồ thị vẫn nằm trong DOT, và trình chỉnh sửa tiếp nhận quyết định cách cho phép thao tác với hình đó.
Nguồn tham khảo
- Graphviz — image — Tài nguyên ảnh nút cục bộ và kích thước SVG bắt buộc.
- Graphviz — imagescale — Co giãn đồng đều cho vừa và co giãn chiều rộng/chiều cao độc lập.
- Graphviz — đầu ra SVG — Đầu ra tích hợp và Cairo, cùng ý nghĩa của svg_inline.
- Viz.js — API — Siêu dữ liệu kích thước ảnh, đơn vị rõ ràng và lệnh kết xuất SVG.
- MDN — SVG dưới dạng ảnh — Hạn chế tài nguyên bên ngoài trong ngữ cảnh ảnh và khác biệt với nhúng tài liệu.
Thử một nút xuyên suốt quy trình bàn giao trước khi chuẩn bị cả thư viện hình. Nếu chỉ còn họa tiết raster, hãy chuẩn bị một bản hình SVG để đánh giá, kiểm tra khe hở và tỷ lệ, rồi thêm vào đồ thị DOT và xác minh đầu ra đã di chuyển hoặc đóng gói trong trình xem đích.
Thêm từ blog

Ảnh SVG trong WeasyPrint: sửa logo bị thiếu trong PDF
Khắc phục logo SVG bị thiếu trong PDF WeasyPrint bằng URL cơ sở đúng và kích thước CSS rõ ràng, rồi kiểm tra đường dẫn vector, tỷ lệ và hình trong PDF đã lưu.

SVG Matplotlib: Giữ đồ thị và logo dưới dạng đường dẫn
Xuất đồ thị Matplotlib thành SVG, ghép các đường dẫn logo riêng bằng svgutils và kiểm tra tệp bàn giao để tìm pixel nhúng, sai vị trí hoặc thay đổi phông chữ.