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

# SVG feComposite: сравните графику in, out и xor

> Сравните входы фильтров SVG с in, out и xor, проверьте порядок операндов и частичный альфа-канал, сохраните исходные контуры, когда видимое отверстие не является редактируемой геометрией.

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

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

SVG `feComposite` объединяет два отрисованных входа. Для полностью непрозрачных входов `in` сохраняет окрашивание первого в пересечении, `out` — вне пересечения, а `xor` объединяет оба входа вне их общего пересечения. Эти операции меняют окрашивание при отрисовке. Они не переписывают исходные контуры в редактируемое пересечение или разность.

Это различие важно, когда перекрытие выглядит как отверстие, но результату передачи нужны настоящие контуры. Пример ниже сравнивает две оригинальные асимметричные фигуры, меняет входы местами и проверяет частичную прозрачность. Храните исходную графику рядом с результатом фильтра.

## Назовите оба входа до выбора оператора

[Справочник MDN по feComposite](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feComposite) описывает попиксельную операцию в пространстве изображения. `in` задаёт первый вход, `in2` — второй. Давайте промежуточным результатам явные имена, чтобы изменение цепочки фильтра не меняло операнды незаметно.

Для непрозрачных внутренних областей эти три операции легко сравнить:

| Операция | Первый вход A, второй B                        | Что меняет перестановка входов              |
| -------- | ---------------------------------------------- | ------------------------------------------- |
| `in`     | Окрашивание A в пересечении                    | Пересечение несёт окрашивание B             |
| `out`    | Окрашивание A вне B                            | Окрашивание B вне A — другая область        |
| `xor`    | Оба входа вне общего непрозрачного пересечения | Сохраняются те же неперекрывающиеся области |

Тот же атрибут `operator` встречается у других примитивов фильтров с другими значениями. Явно учитывайте контекст композиции: [справочник MDN по operator](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/operator) отличает его от морфологических операций.

**Меняйте видимое окрашивание**

![Концептуальное сравнение перекрывающейся цветной графики и композиции с незакрашенным пересечением](https://perfectvector.com/blog/svg-composite-artwork/overlap-and-paint.webp)

*Иллюстрация: перекрывающиеся входы могут оставить область незакрашенной. Декоративные силуэты и стрелки концептуальны; точные операторы, образцы альфа-канала и неизменные контуры ниже относятся к оригинальному выполненному браузерному тесту.*

## Явно совместите вторую графику

Наш первый операнд A — бирюзовый ступенчатый блок. B — охристый перекошенный воздушный змей. Оба используют один viewBox `0 0 240 160`. B выходит за локальный ограничивающий прямоугольник A, поэтому использовать границы A как область фильтра было бы плохим исходным допущением.

Фильтр использует `filterUnits="userSpaceOnUse"` для явной области `x=0`, `y=0`, `width=240`, `height=160`. [Справочник MDN по filterUnits](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/filterUnits) объясняет выбор координат. Мы также задаём `primitiveUnits="userSpaceOnUse"` и даём второму входу те же координаты полного кадра.

B — самодостаточный data URL SVG, переданный через `feImage` с именем результата `operandB`. Это вводит B в фильтр как входное изображение, а не вставляет контур B как новый прямой дочерний элемент фильтруемой графики. [Справочник MDN по feImage](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feImage) описывает поведение входного изображения.

Фильтр явно выбирает `sRGB`. По умолчанию эти примитивы используют `linearRGB`, как описано в справочнике feComposite. Ни значение по умолчанию, ни имя оператора не дают операции правки контуров.

## Запустите полное оригинальное сравнение

Сохраните это как `starter.html` и раздавайте папку по локальному HTTP, например с `python3 -m http.server 8766 --bind 127.0.0.1`. Откройте `http://127.0.0.1:8766/starter.html`; при необходимости используйте другой свободный порт.

Страница создаёт два оригинала и семь фильтрованных случаев в каждом из двух явных размеров. Каждый ID фильтра включает случай и ширину, чтобы несколько встроенных SVG в одном документе имели уникальные ссылки. Каждая ссылка «Сохранить SVG» сохраняет самодостаточный фильтр и закодированный вход B.

```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>
```

Код сохраняет тот же прямой контур A даже при обратном порядке входов оператора. Например, `b-in-a` меняет `feComposite` на `in="operandB"` и `in2="SourceGraphic"`, а не заменяет фильтруемый исходный элемент на B. Это показывает порядок операндов, не меняя лежащую в основе геометрию A.

Проверка пикселей здесь читает canvas, нарисованный из каждого созданного SVG. Загружаемый результат всё ещё фильтрованный SVG. Он не является новым булевым контуром или преобразованием PerfectVector.

## Сравнивайте окрашивание и геометрию отдельно

Мы выполнили эту точную страницу в одном окружении Chrome при `120 × 80` и `240 × 160`, сохранили все 18 SVG и снова открыли их как изображения в том же браузере. Показанные размеры — явные входные значения, а не утверждение о двух физических устройствах.

Три внутренние позиции образцов используют исходную систему координат: только A `(40,40)`, только B `(200,84)` и пересечение `(120,84)`. Следующие значения альфа-канала наблюдались в обоих размерах при непрозрачных операндах:

| Входы фильтра и оператор | Альфа только A | Альфа только B | Альфа пересечения |
| ------------------------ | -------------- | -------------- | ----------------- |
| 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                 |

Строки `in` имеют общее непрозрачное пересечение, но разный цвет: A первым давал бирюзовый `(23,107,91,255)`, B первым — охру `(212,165,58,255)`. Внешний образец `(230,150)` оставался прозрачным всё время. Это выбранные внутренние пиксели, а не полный тест покрытия краёв или совместимости.

Каждый фильтрованный файл всё ещё имел точную исходную строку `d` A и совпадающий SHA-256. Его локальный геометрический `getBBox()` оставался `x=24`, `y=24`, `width=168`, `height=112`. Этот прямоугольник описывает исходный контур, а не видимые границы пикселей фильтра. Закодированный контур B тоже не менялся. Поэтому результат фильтра может выглядеть иначе, хотя оба созданных контура остаются целыми.

Сохранённые оригиналы имеют один прямой контур и не имеют изображения фильтра. В каждом фильтрованном файле один прямой контур A плюс один `feImage`, несущий отдельный SVG B из одного контура. Обычный растровый элемент `image` не добавляется. Отрисованная операция в пространстве изображения и векторные исходные операнды могут сосуществовать; один перечень исходных элементов не означает, что результат стал редактируемой объединённой геометрией.

## Частичная непрозрачность меняет смысл отверстия

Последний случай делает B наполовину непрозрачным, оставляя A непрозрачным, затем применяет A `out` B. Пересечение не стало пустым. В обоих размерах наблюдаемый RGBA был `(22,106,90,127)`: частично прозрачный бирюзовый с округлением конвейера отрисовки/чтения.

Для `out` выходной альфа-канал равен первому альфа-каналу, умноженному на единицу минус второй. Для `in` — их произведению. [Определение композиции Filter Effects](https://www.w3.org/TR/filter-effects-1/#feCompositeElement) определяет операции через предварительно умноженные цвета и альфа-канал. Непрозрачный B может удалить перекрывающееся окрашивание A, а частично прозрачный B оставляет его часть.

Проверяйте результат на настоящем фоне. Бледная область поверх белого может быть полупрозрачной краской, а не полностью прозрачным отверстием. Сглаженные краевые пиксели тоже требуют визуальной проверки; внутренний образец не обещает нулевого альфа-канала у каждого граничного пикселя. Для отдельной задачи переназначения непрозрачности см. [руководство по альфа-порогам SVG](https://perfectvector.com/ru/blog/svg-alpha-threshold).

## Передавайте эффект фильтра или создавайте настоящие контуры

Сохраняйте фильтр, если принимающее средство отрисовки должно воспроизвести визуальную композицию. Сохраняйте исходные файлы A и B и проверяйте заново открытый фильтрованный SVG в реальной целевой среде. Наше успешное открытие в браузере не сертифицирует другие средства отрисовки или производственные машины.

Если передаче нужны выделяемые объединённые контуры или отверстие для резки, выполните и проверьте настоящую правку контуров или булеву операцию в нужном процессе. Изменённое видимое окрашивание здесь не создаёт этой геометрии. [Руководство clipPath и mask](https://perfectvector.com/ru/blog/svg-clippath-vs-mask) поясняет связанное различие видимости; [руководство по разгруппировке SVG](https://perfectvector.com/ru/blog/svg-wont-ungroup) помогает, когда показанная графика не является ожидаемым редактируемым объектом.

Если клипарт существует только в пикселях, а нужны редактируемые исходные фигуры, [подготовьте SVG-клипарт с PerfectVector](https://perfectvector.com/ru/clipart-to-svg), проверьте контуры и отверстия и сохраните мастер. Применяйте и проверяйте нужный фильтр или операцию с контурами отдельно. Векторизация не превращает визуальное пересечение этого фильтра в проверенный производственный контур.

## Частые вопросы

**Удаляет ли feComposite out геометрию перекрывающегося контура?**
Нет. Он меняет отрисованное окрашивание по альфа-каналу второго входа. В наших фильтрованных файлах исходные данные контура A и локальные геометрические границы не менялись даже там, где перекрывающееся окрашивание стало прозрачным.

**Почему перестановка in и in2 меняет результат?**
Они задают первый и второй входы. In сохраняет окрашивание первого в пределах непрозрачности второго; out — вне неё. Обратные случаи in имеют общее непрозрачное пересечение, но разные цвета, а обратные out сохраняют разные области.

**Всегда ли xor делает пересечение полностью пустым?**
Полностью непрозрачное внутреннее пересечение было пустым в наших случаях xor. Частичный альфа-канал и сглаженные края требуют отдельной проверки; диаграммы множеств непрозрачных фигур не описывают каждый полупрозрачный пиксель.

**Можно ли передать фильтрованное отверстие прямо как редактируемый контур резки?**
Визуальный результат фильтра не является заново созданной булевой геометрией. Сохраните исходные фигуры, создайте и проверьте нужные контуры в целевом процессе работы с ними и отдельно проверьте принимающее приложение и производственные требования.

## Источники

1. [MDN: feComposite](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feComposite) — Роли входов пространства изображения, описания операторов и стандартное цветовое пространство фильтра.
2. [MDN: operator](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/operator) — Значения операторов композиции и отдельный контекст морфологии.
3. [MDN: filterUnits](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/filterUnits) — Система координат области фильтра.
4. [MDN: feImage](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feImage) — Изображение на входе конвейера фильтра.
5. [W3C: Композиция Filter Effects](https://www.w3.org/TR/filter-effects-1/#feCompositeElement) — Определения композиции предварительно умноженных цвета и альфа-канала.

***

Начинаете со своего растрового клипарта? [Создайте редактируемый мастер SVG](https://perfectvector.com/ru/clipart-to-svg), проверьте контуры и отверстия, затем сохраняйте его, проверяя выбранную визуальную композицию или отдельно созданный результат контуров в целевой среде.

## Explore

- [Read the HTML article](https://perfectvector.com/ru/blog/svg-composite-artwork)
- [Обрежьте SVG окончательно, без скрытых контуров](https://perfectvector.com/ru/blog/permanent-crop-svg.md)
- [Inkscape: чем отличаются Object to Path и Stroke to Path](https://perfectvector.com/ru/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)
