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

# SVG feComposite: so sánh hình với in, out và xor

> So sánh đầu vào bộ lọc SVG bằng in, out và xor, thử thứ tự toán hạng cùng alpha một phần, và giữ đường dẫn nguồn khi khoảng trống hiển thị không phải hình học chỉnh sửa được.

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

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

SVG `feComposite` kết hợp hai đầu vào được kết xuất. Với đầu vào đục hoàn toàn, `in` giữ màu tô đầu vào thứ nhất trong phần chồng lấp, `out` giữ nó ngoài phần chồng lấp và `xor` kết hợp cả hai đầu vào bên ngoài phần chồng lấp chung. Những phép này thay đổi màu tô khi kết xuất. Chúng không viết lại đường dẫn nguồn thành phần giao hay phần trừ có thể chỉnh sửa.

Khác biệt đó quan trọng khi chỗ chồng lấp trông như khoảng trống nhưng tệp bàn giao cần đường bao thực. Ví dụ bên dưới so sánh hai hình bất đối xứng gốc, đảo đầu vào và kiểm tra độ trong suốt một phần. Giữ hình nguồn cạnh kết quả có bộ lọc.

## Đặt tên cả hai đầu vào trước khi chọn toán tử

[Tài liệu tham khảo feComposite của MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feComposite) mô tả phép theo từng pixel trong không gian ảnh. `in` đặt tên đầu vào thứ nhất; `in2` đặt tên đầu vào thứ hai. Đặt tên tường minh cho các kết quả trung gian để thay đổi chuỗi bộ lọc không âm thầm thay toán hạng.

Với vùng trong đục, ba phép này dễ so sánh:

| Phép  | Đầu vào thứ nhất A, thứ hai B                 | Đảo đầu vào thay đổi gì                   |
| ----- | --------------------------------------------- | ----------------------------------------- |
| `in`  | Màu tô của A trong phần chồng lấp             | Phần chồng lấp mang màu tô của B thay thế |
| `out` | Màu tô của A ngoài B                          | Màu tô của B ngoài A là vùng khác         |
| `xor` | Cả hai đầu vào ngoài phần chồng lấp đục chung | Cùng các vùng không chồng lấp được giữ    |

Cùng thuộc tính `operator` cũng xuất hiện trên các phần tử bộ lọc khác với giá trị khác. Giữ rõ ngữ cảnh tổng hợp; [tài liệu tham khảo operator của MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/operator) phân biệt nó với phép hình thái.

**Thay màu tô nhìn thấy**

![So sánh khái niệm hình màu chồng lấp và hình tổng hợp có phần chồng lấp không được tô](https://perfectvector.com/blog/svg-composite-artwork/overlap-and-paint.webp)

*Minh họa: các đầu vào chồng lấp có thể để một vùng không được tô. Dáng bao trang trí và mũi tên mang tính khái niệm; toán tử chính xác, mẫu alpha và đường dẫn giữ nguyên bên dưới đến từ mẫu trình duyệt gốc đã chạy.*

## Căn chỉnh hình thứ hai tường minh

Toán hạng đầu A là khối bậc thang màu xanh mòng két. B là hình diều xiên màu đất vàng. Cả hai dùng cùng viewBox `0 0 240 160`. B vượt ra ngoài hộp bao cục bộ của A, nên dùng phạm vi A làm vùng bộ lọc là giả định khởi đầu kém phù hợp.

Bộ lọc dùng `filterUnits="userSpaceOnUse"` cho vùng tường minh `x=0`, `y=0`, `width=240`, `height=160`. [Tài liệu tham khảo filterUnits của MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/filterUnits) giải thích lựa chọn tọa độ đó. Chúng tôi cũng đặt `primitiveUnits="userSpaceOnUse"` và cho đầu vào thứ hai cùng tọa độ toàn khung.

B là data URL SVG độc lập được truyền qua `feImage`, có tên kết quả `operandB`. Cách này đưa B vào bộ lọc như đầu vào ảnh; nó không chèn đường dẫn B làm phần tử con trực tiếp mới của hình được lọc. [Tài liệu tham khảo feImage của MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feImage) mô tả hành vi đầu vào ảnh.

Bộ lọc chọn `sRGB` tường minh. Mặc định của những phần tử bộ lọc này là `linearRGB`, như tài liệu feComposite mô tả. Cả mặc định đó lẫn tên toán tử đều không cung cấp phép chỉnh sửa đường dẫn.

## Chạy phép so sánh gốc hoàn chỉnh

Lưu thành `starter.html` và phục vụ thư mục qua HTTP cục bộ, chẳng hạn bằng `python3 -m http.server 8766 --bind 127.0.0.1`. Mở `http://127.0.0.1:8766/starter.html`; dùng cổng trống khác nếu cần.

Trang tạo hai bản gốc cùng bảy trường hợp có bộ lọc ở mỗi kích thước trong hai kích thước tường minh. Mỗi ID bộ lọc gồm trường hợp và chiều rộng để nhiều SVG nội tuyến trong cùng tài liệu có tham chiếu riêng. Mỗi liên kết Lưu SVG giữ bộ lọc độc lập và đầu vào B đã mã hóa.

```html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Original SVG composite artwork</title>
<style>
  body { margin: 24px; font: 16px system-ui; background: #f6f2e8; }
  main { display: grid; grid-template-columns: repeat(3, 260px); gap: 18px; }
  figure { margin: 0; }
  svg { display: block; background: white; border: 1px solid #bbb; }
  figcaption { margin: 6px 0; }
  pre { white-space: pre-wrap; font-size: 12px; }
</style>
<h1>Original operands and rendered composites</h1>
<main id="cases"></main>
<pre id="report"></pre>
<script>
  const A = 'M24 24 H132 V56 H192 V136 H24 Z';
  const B = 'M92 8 L216 84 L92 152 L60 84 Z';
  const svgNS = 'http://www.w3.org/2000/svg';
  const cases = [
    { id: 'a' }, { id: 'b' },
    { id: 'a-in-b', operator: 'in' },
    { id: 'a-out-b', operator: 'out' },
    { id: 'a-xor-b', operator: 'xor' },
    { id: 'b-in-a', operator: 'in', reverse: true },
    { id: 'b-out-a', operator: 'out', reverse: true },
    { id: 'b-xor-a', operator: 'xor', reverse: true },
    { id: 'a-out-half-b', operator: 'out', opacity: 0.5 },
  ];
  function documentSVG(test, width) {
    const height = width * 2 / 3;
    const id = test.id + '-' + width;
    const second = '<svg xmlns="' + svgNS + '" width="240" height="160" viewBox="0 0 240 160">'
      + '<path d="' + B + '" fill="#d4a53a" opacity="' + (test.opacity ?? 1) + '"/></svg>';
    const href = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(second);
    const first = test.reverse ? 'operandB' : 'SourceGraphic';
    const other = test.reverse ? 'SourceGraphic' : 'operandB';
    const defs = test.operator ? '<defs><filter id="' + id + '" filterUnits="userSpaceOnUse" primitiveUnits="userSpaceOnUse" x="0" y="0" width="240" height="160" color-interpolation-filters="sRGB">'
      + '<feImage href="' + href + '" x="0" y="0" width="240" height="160" preserveAspectRatio="none" result="operandB"/>'
      + '<feComposite in="' + first + '" in2="' + other + '" operator="' + test.operator + '"/></filter></defs>' : '';
    return '<svg xmlns="' + svgNS + '" width="' + width + '" height="' + height + '" viewBox="0 0 240 160">'
      + defs + '<path d="' + (test.id === 'b' ? B : A) + '" fill="' + (test.id === 'b' ? '#d4a53a' : '#176b5b')
      + '"' + (test.operator ? ' filter="url(#' + id + ')"' : '') + '/></svg>';
  }
  async function run() {
    const results = [];
    for (const width of [120, 240]) {
      for (const test of cases) {
        const source = documentSVG(test, width);
        const svg = new DOMParser().parseFromString(source, 'image/svg+xml').documentElement;
        const figure = document.createElement('figure');
        const caption = document.createElement('figcaption');
        caption.textContent = test.id + ', ' + width + ' × ' + width * 2 / 3;
        figure.append(document.importNode(svg, true), caption);
        document.getElementById('cases').append(figure);
        const path = figure.querySelector('path');
        const bbox = path.getBBox();
        const image = new Image();
        image.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(source);
        await image.decode();
        const canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = width * 2 / 3;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
        const sample = (x, y) => [...ctx.getImageData(Math.floor(x * width / 240), Math.floor(y * width / 240), 1, 1).data];
        const hash = [...new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(path.getAttribute('d'))))]
          .map(v => v.toString(16).padStart(2, '0')).join('');
        const download = document.createElement('a');
        download.href = image.src;
        download.download = test.id + '-' + width + '.svg';
        download.textContent = 'Save SVG';
        figure.append(download);
        results.push({ id: test.id, width, height: canvas.height, d: path.getAttribute('d'), dSHA256: hash,
          bbox: { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height },
          directPaths: svg.querySelectorAll('path').length, filterImages: svg.querySelectorAll('feImage').length,
          aOnly: sample(40, 40), bOnly: sample(200, 84), overlap: sample(120, 84), outside: sample(230, 150) });
      }
    }
    document.getElementById('report').textContent = JSON.stringify({ A, B, results }, null, 2);
  }
  run();
</script>
</html>
```

Mã giữ cùng đường dẫn A trực tiếp ngay cả khi đảo đầu vào toán tử. Chẳng hạn, `b-in-a` đổi `feComposite` thành `in="operandB"` và `in2="SourceGraphic"`; nó không thay phần tử nguồn được lọc bằng B. Điều này làm rõ thứ tự toán hạng mà không đổi hình học A nền tảng.

Kiểm tra pixel ở đây đọc canvas được vẽ từ mỗi SVG tạo ra. Tệp bàn giao tải xuống vẫn là SVG có bộ lọc. Nó không phải đường dẫn Boolean mới hay kết quả chuyển đổi PerfectVector.

## So sánh màu tô và hình học riêng

Chúng tôi chạy đúng trang này trong một môi trường Chrome ở `120 × 80` và `240 × 160`, lưu cả 18 SVG và mở lại dưới dạng ảnh trong cùng trình duyệt. Kích thước hiển thị là đầu vào tường minh, không phải khẳng định về hai thiết bị vật lý.

Ba vị trí mẫu bên trong dùng hệ tọa độ gốc: chỉ A `(40,40)`, chỉ B `(200,84)` và chồng lấp `(120,84)`. Các giá trị alpha sau được quan sát ở cả hai kích thước với toán hạng đục:

| Đầu vào bộ lọc và toán tử | Alpha chỉ A | Alpha chỉ B | Alpha chồng lấp |
| ------------------------- | ----------- | ----------- | --------------- |
| A `in` B                  | 0           | 0           | 255             |
| A `out` B                 | 255         | 0           | 0               |
| A `xor` B                 | 255         | 255         | 0               |
| B `in` A                  | 0           | 0           | 255             |
| B `out` A                 | 0           | 255         | 0               |
| B `xor` A                 | 255         | 255         | 0               |

Các hàng `in` có chung phần chồng lấp đục nhưng khác màu: A trước là xanh mòng két `(23,107,91,255)`; B trước là đất vàng `(212,165,58,255)`. Mẫu ngoài `(230,150)` giữ trong suốt suốt quá trình. Đây là các pixel bên trong được chọn, không phải kiểm thử đầy đủ về phủ cạnh hay tương thích.

Mọi tệp có bộ lọc vẫn có chính xác chuỗi `d` gốc của A và SHA-256 khớp. `getBBox()` hình học cục bộ giữ ở `x=24`, `y=24`, `width=168`, `height=112`. Hộp đó mô tả đường dẫn nguồn; nó không phải hộp bao pixel bộ lọc nhìn thấy. Đường dẫn B đã mã hóa cũng giữ nguyên. Vì vậy kết quả bộ lọc có thể trông khác trong khi cả hai đường bao tự tạo vẫn nguyên vẹn.

Các bản gốc đã lưu có một đường dẫn trực tiếp và không có ảnh bộ lọc. Mọi tệp có bộ lọc có một đường dẫn A trực tiếp cùng một `feImage` mang SVG một đường dẫn riêng của B. Không có phần tử `image` raster thông thường được thêm. Phép trong không gian ảnh được kết xuất và toán hạng nguồn vector có thể cùng tồn tại; chỉ danh sách phần tử nguồn không có nghĩa kết quả đã thành hình học kết hợp chỉnh sửa được.

## Độ đục một phần thay đổi ý nghĩa của khoảng trống

Trường hợp cuối làm B đục một nửa trong khi giữ A đục, rồi áp dụng A `out` B. Phần chồng lấp không trở thành trống. Ở cả hai kích thước, RGBA quan sát là `(22,106,90,127)`: xanh mòng két trong suốt một phần, với làm tròn từ chuỗi kết xuất/đọc lại.

Với `out`, alpha đầu ra bằng alpha thứ nhất nhân một trừ alpha thứ hai. Với `in`, đó là tích của chúng. [Định nghĩa tổng hợp Filter Effects](https://www.w3.org/TR/filter-effects-1/#feCompositeElement) định nghĩa những phép này bằng màu và alpha được nhân trước. B đục có thể xóa màu tô chồng lấp của A; B trong suốt một phần để lại một ít màu đó.

Kiểm tra kết quả trên nền thực. Vùng nhạt trên trắng có thể là màu tô bán trong suốt thay vì lỗ hoàn toàn trong suốt. Pixel cạnh được khử răng cưa cũng cần xem trực quan; mẫu bên trong không hứa rằng mọi pixel ranh giới có alpha 0. Với công việc ánh xạ lại độ đục riêng, xem [hướng dẫn ngưỡng alpha SVG](https://perfectvector.com/vi/blog/svg-alpha-threshold).

## Bàn giao hiệu ứng bộ lọc hoặc tạo đường bao thật

Giữ bộ lọc này khi bộ kết xuất nhận cần tái hiện hình tổng hợp nhìn thấy. Bảo toàn các tệp A và B gốc, kiểm tra SVG có bộ lọc đã mở lại ở đích thực. Việc mở lại thành công trong trình duyệt của chúng tôi không chứng nhận bộ kết xuất hay máy sản xuất khác.

Nếu tệp bàn giao cần đường bao kết hợp có thể chọn hoặc khoảng trống sẵn cho máy cắt, thực hiện và kiểm tra phép chỉnh sửa đường dẫn hay Boolean thật trong quy trình dự kiến. Màu tô nhìn thấy thay đổi ở đây không tạo hình học đó. [Hướng dẫn clipPath so với mask](https://perfectvector.com/vi/blog/svg-clippath-vs-mask) nêu sự phân biệt hiển thị liên quan; [hướng dẫn bỏ nhóm SVG](https://perfectvector.com/vi/blog/svg-wont-ungroup) giúp khi hình hiển thị không phải đối tượng chỉnh sửa được bạn mong đợi.

Nếu clipart chỉ có dưới dạng pixel và bạn cần hình nguồn chỉnh sửa được, hãy [chuẩn bị SVG clipart bằng PerfectVector](https://perfectvector.com/vi/clipart-to-svg), kiểm tra đường bao và khoảng trống, rồi giữ bản chính. Áp dụng và xác minh bộ lọc hay phép đường dẫn mong muốn riêng. Vector hóa không biến chỗ chồng lấp nhìn thấy của bộ lọc này thành đường bao sản xuất đã xác minh.

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

**feComposite out có xóa hình học đường dẫn chồng lấp không?**
Không. Nó thay màu tô được kết xuất theo alpha đầu vào thứ hai. Trong các tệp có bộ lọc, dữ liệu đường dẫn A gốc và phạm vi hình học cục bộ giữ nguyên ngay cả nơi màu tô chồng lấp trở nên trong suốt.

**Tại sao đổi chỗ in và in2 làm kết quả khác?**
Chúng xác định đầu vào thứ nhất và thứ hai. In giữ màu tô đầu vào thứ nhất trong độ đục của đầu vào thứ hai; out giữ đầu vào thứ nhất ngoài nó. Các trường hợp in đảo của chúng tôi có chung phần chồng lấp đục nhưng hiển thị màu khác, còn out đảo giữ các vùng khác nhau.

**xor có luôn làm phần chồng lấp hoàn toàn trống không?**
Phần chồng lấp bên trong đục hoàn toàn trống trong các trường hợp xor của chúng tôi. Alpha một phần và cạnh khử răng cưa cần kiểm tra riêng; sơ đồ tập hợp hình đục không mô tả mọi pixel bán trong suốt.

**Tôi có thể gửi khoảng trống có bộ lọc trực tiếp như đường cắt chỉnh sửa được không?**
Kết quả hiển thị của bộ lọc không phải hình học Boolean mới được tạo. Giữ hình gốc, tạo và kiểm tra đường bao cần thiết trong quy trình đường dẫn dự kiến, đồng thời xác minh riêng ứng dụng nhận cùng yêu cầu sản xuất.

## Nguồn tham khảo

1. [MDN: feComposite](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feComposite) — Vai trò đầu vào không gian ảnh, mô tả toán tử và không gian màu bộ lọc mặc định.
2. [MDN: operator](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/operator) — Giá trị toán tử tổng hợp và ngữ cảnh hình thái riêng.
3. [MDN: filterUnits](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/filterUnits) — Hệ tọa độ vùng bộ lọc.
4. [MDN: feImage](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feImage) — Đầu vào ảnh cho chuỗi bộ lọc.
5. [W3C: Tổng hợp Filter Effects](https://www.w3.org/TR/filter-effects-1/#feCompositeElement) — Định nghĩa tổng hợp màu và alpha được nhân trước.

***

Bắt đầu bằng clipart raster của bạn? [Tạo bản chính SVG có thể chỉnh sửa](https://perfectvector.com/vi/clipart-to-svg), kiểm tra đường bao và khoảng trống, rồi giữ nó khi kiểm tra hình tổng hợp đã chọn hoặc kết quả đường dẫn được tạo riêng tại đích.

## Explore

- [Read the HTML article](https://perfectvector.com/vi/blog/svg-composite-artwork)
- [Cắt SVG vĩnh viễn, không để lại đường dẫn ẩn](https://perfectvector.com/vi/blog/permanent-crop-svg.md)
- [Inkscape: Object to Path khác Stroke to Path thế nào?](https://perfectvector.com/vi/blog/inkscape-stroke-vs-object-to-path.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
