> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# Ảnh SVG cho nút Cytoscape.js: độ vừa và khoảng đệm

> Đặt hình SVG tùy chỉnh vừa trong nút Cytoscape.js với ví dụ chạy được. So sánh khoảng trắng nguồn, contain và cover, rồi kiểm tra việc tải và vị trí nhãn.

Source: https://perfectvector.com/vi/blog/cytoscape-svg-node-artwork

Language: vi
Author: Irene Kim
Published: 2026-10-02T08:00:00+09:00
Updated: 2026-10-02T08:00:00+09:00

Dùng URL ảnh SVG trong kiểu `background-image` của nút, rồi chọn cách co vừa cho hình bạn muốn hiển thị. Nếu biểu trưng tải được nhưng trông nhỏ xíu, hãy kiểm tra khoảng trống trong khung nhìn SVG trước khi phóng to nút đồ thị. Nếu các đầu bị mất, so sánh tỷ lệ ảnh với nút và kiểm tra việc cắt xén.

Cytoscape.js [có tài liệu về nền nút SVG](https://js.cytoscape.org/#style/background-image), gồm các cách co vừa `contain`, `cover` và `none`. Hướng dẫn này dùng biểu trưng gốc gồm một đường dẫn để tách ranh giới nguồn khỏi định kiểu đồ thị. Giữ bản chính hình có thể chỉnh sửa cạnh cấu hình đồ thị.

## Tách ảnh nguồn khỏi nút đồ thị

Có ba hộp cần kiểm tra: phạm vi phần hình được vẽ, khung nhìn của ảnh SVG và thân nút. [SVG `viewBox`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox) xác định hình chữ nhật tọa độ nguồn được ánh xạ vào khung nhìn. Nó có thể chứa nhiều khoảng trống hơn hẳn phần hình nhìn thấy.

Nguồn có ranh giới sát của chúng tôi là 120 × 60, với biểu trưng màu san hô trải từ x=6 đến x=114 và y=6 đến y=54. Khoảng trống giữa là một phần của cùng đường dẫn:

```svg
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>
<svg xmlns="http://www.w3.org/2000/svg"
     width="120" height="60" viewBox="0 0 120 60">
  <path fill="#f36f59" fill-rule="evenodd"
    d="M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z"/>
</svg>
```

Biến thể có khoảng đệm chỉ đổi kích thước SVG ngoài và `viewBox`:

```svg
<svg xmlns="http://www.w3.org/2000/svg"
     width="200" height="140" viewBox="-40 -40 200 140">
```

Giữ nguyên phần đầu, đường dẫn và thẻ đóng. Hai tệp đều vẽ các tọa độ đường dẫn giống hệt. Tệp thứ hai bao quanh chúng bằng nhiều khoảng trống nguồn hơn. Khoảng trống đó co giãn cùng ảnh, nên thay cách co vừa nền không thể đáng tin cậy thay cho việc chọn ranh giới nguồn phù hợp. [Hướng dẫn hộp bao SVG](https://perfectvector.com/vi/blog/svg-bounding-box) giúp xử lý khi khung nhìn của tệp không khớp với hình nhìn thấy.

## Chạy ví dụ bốn trường hợp

Chúng tôi kiểm thử Cytoscape.js [3.34.3](https://github.com/cytoscape/cytoscape.js/releases/tag/v3.34.3) với gói trình duyệt chính thức được cố định phiên bản và phục vụ cục bộ. Lưu [gói từ thẻ phát hành đó](https://raw.githubusercontent.com/cytoscape/cytoscape.js/v3.34.3/dist/cytoscape.min.js) thành `cytoscape-3.34.3.min.js` cạnh `example.html` bên dưới. Phục vụ thư mục qua HTTP cục bộ, chẳng hạn bằng `python3 -m http.server 8000`, rồi mở `http://localhost:8000/example.html`.

Ví dụ mã hóa SVG gốc thành data URI. [`encodeURIComponent()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) mã hóa thoát các ký tự URI, gồm `#` trong màu tô của chúng tôi. Hướng dẫn SVG của thư viện khuyến nghị cách mã hóa này thay Base64, cùng phần đầu XML được thể hiện ở đây. Đây là một biểu trưng độc lập không có phông chữ hay ảnh bên ngoài.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>SVG node fit comparison</title>
<style>
  body { font: 16px system-ui; margin: 20px; }
  #cy { width: 1100px; height: 250px; border: 1px solid #ddd; }
  #status { white-space: pre-wrap; }
</style>
<div id="cy"></div>
<pre id="status">Loading images</pre>
<script src="cytoscape-3.34.3.min.js"></script>
<script>
const header = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>';
const path = 'M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z';
function artwork(padded) {
  const width = padded ? 200 : 120;
  const height = padded ? 140 : 60;
  const viewBox = padded ? '-40 -40 200 140' : '0 0 120 60';
  return header + `<svg xmlns="http://www.w3.org/2000/svg"
    width="${width}" height="${height}" viewBox="${viewBox}">
    <path fill="#f36f59" fill-rule="evenodd" d="${path}"/></svg>`;
}
const cases = [
  ['tight contain', false, 'contain'],
  ['tight cover', false, 'cover'],
  ['padded contain', true, 'contain'],
  ['padded cover', true, 'cover']
].map(([label, padded, fit]) => ({
  label, fit,
  image: 'data:image/svg+xml;utf8,' + encodeURIComponent(artwork(padded))
}));
Promise.all(cases.map(item => new Promise((resolve, reject) => {
  const image = new Image();
  image.onload = () => resolve({
    label: item.label,
    width: image.naturalWidth,
    height: image.naturalHeight
  });
  image.onerror = () => reject(new Error(item.label + ' failed to load'));
  image.src = item.image;
}))).then(loaded => {
  cytoscape({
    container: document.getElementById('cy'),
    elements: cases.map((item, index) => ({
      data: { id: 'n' + index, ...item },
      position: { x: 110 + index * 260, y: 95 }
    })),
    style: [{ selector: 'node', style: {
      width: 120, height: 80, padding: 0, shape: 'rectangle',
      'background-color': '#f1f3f5',
      'background-image': 'data(image)',
      'background-fit': node => node.data('fit'),
      'background-width': 'auto', 'background-height': 'auto',
      'background-width-relative-to': 'inner',
      'background-height-relative-to': 'inner',
      'background-position-x': '50%', 'background-position-y': '50%',
      'background-repeat': 'no-repeat', 'background-clip': 'node',
      'border-width': 1, 'border-color': '#222',
      label: 'data(label)', 'text-valign': 'bottom',
      'text-halign': 'center', 'text-margin-y': 10, 'font-size': 12
    }}],
    layout: { name: 'preset', fit: false },
    zoom: 1, pan: { x: 0, y: 0 },
    userZoomingEnabled: false, userPanningEnabled: false,
    boxSelectionEnabled: false
  });
  document.getElementById('status').textContent =
    'Cytoscape ' + cytoscape.version + '\n' +
    JSON.stringify(loaded, null, 2);
}).catch(error => {
  document.getElementById('status').textContent = error.message;
});
</script>
</html>
```

Khối trạng thái báo kích thước các ảnh được tải trước khi khởi tạo đồ thị. `naturalWidth` đọc chiều rộng nội tại của ảnh, đã hiệu chỉnh theo mật độ, bằng pixel CSS như [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth) mô tả. Trong mẫu kiểm thử này, các ảnh có ranh giới sát báo 120 × 60, còn các ảnh có khoảng đệm báo 200 × 140. Đó là kích thước ảnh, không phải số đo đường dẫn màu san hô.

## So sánh thay đổi ở cùng kích thước nút

Cả bốn nút mô hình đều là 120 × 80 với khoảng đệm nút bằng 0. Chúng tôi kiểm tra mẫu gốc trong Chrome ở mức phóng đại đồ thị 1 và 1,5. Kiểu nút vẫn là 120 × 80; kích thước kết xuất được báo thành 180 × 120 ở mức 1,5. Đây là phép so sánh tĩnh trong trình duyệt đó, không phải phép đo tương thích hay hiệu năng phóng đại.

| Nguồn và cách co vừa   | Hình thức quan sát trong mẫu này                                                                       |
| ---------------------- | ------------------------------------------------------------------------------------------------------ |
| Ranh giới sát, contain | Biểu trưng đầy đủ, thấy các đầu nhọn                                                                   |
| Ranh giới sát, cover   | Biểu trưng lớn hơn với đầu trái và phải bị cắt ở nút                                                   |
| Có khoảng đệm, contain | Biểu trưng nhỏ hơn được bao quanh bởi nhiều khoảng trống                                               |
| Có khoảng đệm, cover   | Lớn hơn một chút so với bản có khoảng đệm dùng contain, vẫn nhỏ hơn nhiều so với các bản ranh giới sát |

Nguồn có ranh giới sát có tỷ lệ ảnh 2:1, trong khi nút là 1,5:1. Đặt toàn bộ ảnh 120 × 60 vừa bên trong 120 × 80 sẽ để lại khoảng trống dọc. Phủ kín nút đó sẽ co giãn ảnh thành 160 × 80 trước khi cắt, nên các đầu ngang nhô ra ngoài thân nút.

Với nguồn có khoảng đệm, hình chữ nhật ảnh khả dụng chứa thêm 40 đơn vị ở mỗi bên. Với contain, tỷ lệ bị giới hạn bởi 80/140 thay vì 120/200. Vì vậy biểu trưng giữ nguyên chiều rộng 108 đơn vị chiếm khoảng 62 đơn vị mô hình. Con số đó là phép tính từ các kích thước khai báo, không phải số đo pixel của ảnh chụp màn hình.

**Ranh giới nguồn và cách co vừa**

![Minh họa biểu trưng nhỏ có nhiều khoảng trắng nguồn, biểu trưng đầy đủ lớn hơn bên trong khung nút và biểu trưng bị khung hẹp hơn cắt mất các đầu.](https://perfectvector.com/blog/cytoscape-svg-node-artwork/source-bounds-fit.webp)

*Minh họa: khoảng trắng nguồn và cách co vừa có thể thay đổi hình nhìn thấy một cách độc lập. Sơ đồ khái niệm này không phải ảnh chụp Cytoscape hay kết quả chuyển đổi.*

## Chọn cách co vừa sau khi xem ranh giới hình

Bắt đầu với nguồn ranh giới sát và contain khi toàn bộ biểu trưng quan trọng. Giữ đủ lề nguồn cho mọi nét hoặc hiệu ứng phải còn nhìn thấy. Thu khung nhìn quá sát có thể cắt mất phần hình hợp lệ; đây không phải chỉ dẫn xóa mọi lề.

Dùng cover khi thiết kế chấp nhận cắt cạnh. Trong ví dụ của chúng tôi, nó giấu các đầu nhọn nên là lựa chọn kém phù hợp nếu các đầu đó giúp nhận diện biểu trưng. Nút rộng hơn có thể thay tỷ lệ co vừa và làm lộ các đầu, nhưng cũng thay đổi bố cục đồ thị. Tăng cả hai kích thước theo tỷ lệ giữ nguyên cách cắt. Hãy quyết định ràng buộc nào bạn muốn thay đổi.

Giữ `background-width` và `background-height` ở `auto` cho phép so sánh này. Các giá trị tường minh có thể ghi đè kích thước ảnh được dùng để co vừa. `padding` của nút là một đầu vào riêng khác; thư viện mô tả kích thước nền có tính nó hay dùng phần thân bên trong. Xem [tài liệu tham khảo background-image](https://js.cytoscape.org/#style/background-image) trước khi thêm các tùy chọn đó. Mẫu có khoảng đệm bằng 0 của chúng tôi trước tiên cô lập khoảng trắng nguồn.

Với quyết định meet, slice và căn chỉnh ở cấp SVG, tiếp tục với [hướng dẫn preserveAspectRatio](https://perfectvector.com/vi/blog/svg-preserveaspectratio). Thay cách co vừa bên trong SVG và thay cách co vừa nền của Cytoscape là hai thao tác riêng.

## Chẩn đoán việc tải trước khi chẩn đoán cắt xén

Nếu trạng thái báo tải thất bại, bước tiếp theo không phải đổi contain sang cover. Mở riêng tài nguyên ảnh, kiểm tra URL và kích thước khai báo, rồi rút gọn về biểu trưng độc lập chỉ gồm đường dẫn ở trên. Với data URI, mã hóa toàn bộ chuỗi SVG thay vì ghép mã đánh dấu thô hoặc giá trị màu chưa được mã hóa thoát.

SVG dùng làm ảnh có các hạn chế khác SVG mở như tài liệu. [Hướng dẫn SVG làm ảnh của MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image) mô tả các hạn chế với tập lệnh và tài nguyên bên ngoài trong ngữ cảnh ảnh. Tệp hình phụ thuộc vào bảng kiểu hoặc phông chữ ngoài cần kiểm thử bàn giao riêng. Ví dụ này tránh những phụ thuộc đó và đặt nhãn đồ thị ngoài SVG.

Nếu ảnh tải được, kiểm tra cách co vừa và cắt xén ở nút bằng một hình rộng rõ ràng. Sau đó thử hình thực tế ở kích thước nút và các môi trường trình duyệt mà ứng dụng hỗ trợ. Tài liệu Cytoscape ghi nhận các điểm cần lưu ý về SVG tùy trình duyệt; quan sát trong Chrome này không giải quyết chúng cho Firefox hay mọi bộ máy khác.

## Giữ nhãn và hình có thể chỉnh sửa riêng biệt

Ví dụ dùng `label: 'data(label)'` cho nhãn đồ thị và không chứa văn bản SVG. Bạn có thể đổi nội dung nhãn mà không dựng lại biểu trưng. Đường dẫn SVG ở trong bản chính nguồn, còn đồ thị quản lý định danh nút, vị trí và quan hệ.

Mẫu được kiểm tra vẽ lên các bề mặt Canvas. Việc thấy nền SVG ở đó không biến các đường dẫn bên trong thành những phần tử đồ thị có thể chỉnh sửa riêng. Giữ bản chính khi cần đổi khoảng trống, dáng bao hoặc màu. Xuất đồ thị là quy trình riêng cần chọn bộ xuất và kiểm thử bàn giao riêng; hướng dẫn này không hứa rằng đồ thị đã xuất sẽ giữ các đường dẫn biểu trưng có thể chỉnh sửa. [Hướng dẫn hình Graphviz](https://perfectvector.com/vi/blog/graphviz-svg-node-images) tìm hiểu việc bàn giao tham chiếu ảnh trong một bộ kết xuất sơ đồ khác.

Nếu biểu trưng tùy chỉnh chỉ có ở dạng PNG hoặc JPG, hãy [chuyển nguồn đó thành hình vector](https://perfectvector.com/vi/image-to-vector), rồi kiểm tra dáng bao, khoảng trống và chi tiết nhỏ trước khi đặt ranh giới SVG. PerfectVector có thể giúp khôi phục hình học nguồn có thể chỉnh sửa. Định kiểu nền, nhãn nút và xuất đồ thị vẫn là các bước riêng. SVG có sẵn phù hợp có thể đi thẳng đến kiểm tra cách co vừa.

## Câu hỏi thường gặp

**Tại sao ảnh SVG trong nút nhỏ xíu dù dùng cover?**
Ảnh nguồn có thể chứa nhiều khoảng trống khung nhìn quanh đường dẫn. So sánh một bản sao có ranh giới sát ở cùng kích thước nút trước khi thay bố cục đồ thị.

**Tôi nên dùng contain hay cover cho biểu trưng tùy chỉnh?**
Chọn contain khi toàn bộ biểu trưng quan trọng. Chỉ chọn cover khi phần cạnh bị cắt quan sát được chấp nhận được với thiết kế, và xác minh bằng nguồn cùng hình nút của bạn.

**Nền nút SVG có tạo các đường dẫn đồ thị có thể chỉnh sửa không?**
Mẫu Canvas đã kiểm thử dùng SVG để vẽ ảnh. Giữ bản chính hình để sửa đường dẫn; các đường bao bên trong không phải nút hay cạnh đồ thị riêng trong ví dụ này.

**Tôi có thể đặt nhãn trong SVG không?**
Ví dụ này giữ nhãn trong dữ liệu đồ thị và dùng hình chỉ gồm đường dẫn. Văn bản SVG, phông chữ và các phụ thuộc của ngữ cảnh ảnh cần kiểm tra trình duyệt và bàn giao riêng.

## Nguồn tham khảo

1. [Cytoscape.js — Ảnh nền](https://js.cytoscape.org/#style/background-image) — định kiểu URL ảnh, co vừa, ghi đè kích thước, mốc tham chiếu khoảng đệm và các điểm cần lưu ý về SVG.
2. [Cytoscape.js — Bản phát hành v3.34.3](https://github.com/cytoscape/cytoscape.js/releases/tag/v3.34.3) — bản phát hành cố định dùng cho mẫu gốc.
3. [Cytoscape.js — Gói trình duyệt v3.34.3](https://raw.githubusercontent.com/cytoscape/cytoscape.js/v3.34.3/dist/cytoscape.min.js) — bản triển khai chính thức theo thẻ được phục vụ cục bộ cho kiểm thử trình duyệt.
4. [MDN — viewBox](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/viewBox) — hình chữ nhật tọa độ nguồn và ánh xạ khung nhìn.
5. [MDN — encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) — mã hóa thoát thành phần data URI của SVG.
6. [MDN — naturalWidth](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth) — kích thước ảnh đã tải, khác với ranh giới đường dẫn.
7. [MDN — SVG làm ảnh](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image) — hạn chế ngữ cảnh ảnh và kiểm tra phụ thuộc.

Nếu biểu trưng bắt đầu từ raster, hãy [tạo bản chính SVG có thể chỉnh sửa](https://perfectvector.com/vi/image-to-vector), kiểm tra đường bao và ranh giới nguồn, rồi so sánh contain và cover trong bố cục nút của bạn.

## Explore

- [Read the HTML article](https://perfectvector.com/vi/blog/cytoscape-svg-node-artwork)
- [Marker SVG Leaflet: căn đầu nhọn bằng iconAnchor](https://perfectvector.com/vi/blog/leaflet-svg-marker-anchor.md)
- [Đo độ dài đường dẫn SVG mà không nhầm tỷ lệ](https://perfectvector.com/vi/blog/measure-svg-path-length.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
