PerfectVector
작성: Irene Kim6분 읽기

Paper.js SVG 불리언 연산: 가져온 아트워크 자르기와 합치기

SVG 경로를 Paper.js로 가져와 겹치는 도형을 합치고 실제 구멍을 뺀 뒤, 재현 가능한 작은 브라우저 예제로 내보낸 파일을 확인하세요.

목차

SVG를 가져와 원하는 경로 객체를 찾은 다음, unite()로 채워진 영역을 합치거나 subtract()로 한 영역에서 다른 영역을 제거하세요. 결과를 확인할 때까지 피연산자를 보관하고, 내보낸 SVG를 다른 곳에서 사용하기 전에 다시 열어 확인하세요.

중요한 결정은 불리언 연산 전에 이루어집니다. 어떤 도형을 함께 묶어야 할까요? 가져온 그룹에는 배경 사각형, 클리핑 경로, 글자, 장식 요소가 들어 있을 수 있습니다. 모든 자식 요소를 합치면 유지하려던 구분이 사라질 수 있습니다. 이 안내에서는 이름이 지정된 닫힌 경로 세 개를 사용하여 무엇이 달라지는지 정확히 보여 줍니다.

식별할 수 있는 채워진 도형으로 시작하기

Paper.js의 SVG 가져오기 기능은 SVG 마크업, SVG 요소 또는 URL을 받습니다. 각 방식은 로딩 처리가 다릅니다. 이 예제는 인라인 문자열을 가져오며, 원격 파일은 로딩 후 가져오기 콜백에서 처리해야 합니다.

이 작업의 피연산자는 Path 또는 CompoundPath 객체여야 합니다. 그룹은 컨테이너이며, 래스터 이미지는 경로 불리언 연산에 필요한 경계를 제공하지 않습니다. 파일이 하나의 그림처럼만 동작한다면 먼저 SVG의 그룹을 해제할 수 없는 이유를 확인하세요.

직접 관리하는 부분에는 ID를 사용하세요. 임의의 내보내기 결과에서 children[0]이 항상 ‘로고’를 뜻한다고 가정하지 마세요. 낯선 아트워크를 살펴보고 각 부분을 의도적으로 지정하세요. 기존 복합 경로의 하위 경로가 이미 원하는 구멍을 정의한다면 그대로 유지하세요.

작은 예제로 가져오기, 합집합, 차집합 실행하기

다음 코드는 브라우저에서 Paper.js 0.12.18로 테스트했습니다. 아트워크는 직접 작성한 원본 SVG로, 정사각형 몸체, 겹치는 돌출부, 원하는 구멍을 표시하는 흰색 정사각형으로 구성됩니다. PerfectVector 변환 샘플은 아닙니다.

빈 폴더에 버전이 고정된 라이브러리를 설치하세요.

npm install --save-exact paper@0.12.18

다음을 index.html로 저장하세요.

<!doctype html>
<meta charset="utf-8">
<title>SVG Boolean example</title>
<canvas id="work" width="300" height="220" hidden></canvas>
<div id="result" style="background:#d8e8e0; width:300px"></div>
<pre id="svg-output"></pre>
<script src="node_modules/paper/dist/paper-full.min.js"></script>
<script src="example.js"></script>

다음을 example.js로 저장한 뒤 브라우저에서 HTML을 여세요.

paper.setup(document.getElementById('work'));
const source = `<svg xmlns="http://www.w3.org/2000/svg" width="300" height="220" viewBox="0 0 300 220">
  <path id="body" fill="#176b62" d="M40 40H180V180H40Z"/>
  <path id="tab" fill="#ee9852" d="M160 80H260V140H160Z"/>
  <path id="hole" fill="#ffffff" d="M80 80H130V130H80Z"/>
</svg>`;
const imported = paper.project.importSVG(source, { insert: false, expandShapes: true });
function operand(name) {
  const item = imported.getItem({ name });
  if (!(item instanceof paper.Path || item instanceof paper.CompoundPath)) {
    throw new Error(`Expected path geometry for ${name}`);
  }
  return item;
}
const joined = operand('body').unite(operand('tab'), { insert: false });
const cut = joined.subtract(operand('hole'), { insert: false });
cut.fillColor = '#176b62';
cut.strokeColor = null;
paper.project.activeLayer.addChild(cut);
const output = paper.project.exportSVG({ asString: true, bounds: new paper.Rectangle(0, 0, 300, 220) });
document.getElementById('result').innerHTML = output;
document.getElementById('svg-output').textContent = output;

가져온 항목은 insert: false로 장면 밖에 유지됩니다. expandShapes: true는 가져오기 기능에 지원되는 기본 도형을 경로로 변환하도록 요청합니다. 이 테스트 자료에는 이미 경로 요소가 들어 있습니다. 가져온 ID가 컨테이너나 다른 항목 유형을 가리킬 수도 있으므로 명시적인 클래스 확인은 여전히 중요합니다.

불리언 API는 새로운 경로 항목을 반환합니다. 여기서는 최종적으로 잘라낸 도형을 추가할 때까지 결과를 장면 밖에 둡니다. 원본 부분은 imported 아래에 남아 있으므로 연산이 실패해도 소스를 다시 구성할 필요가 없습니다.

joined.subtract(hole)은 합쳐진 실루엣에서 구멍으로 만들 영역을 빼냅니다. 피연산자의 순서를 바꾸면 다른 연산이 되어 비어 있거나 예상과 다른 결과가 나올 수 있습니다. Paper.js의 기본 차집합 모드는 피연산자를 면적으로 취급합니다. trace 옵션은 불리언 도형 처리에 관한 것으로, PNG를 벡터로 추적하는 작업과는 관계없습니다.

가져온 SVG 경로 세 개, 투명한 정사각형 구멍이 있는 합쳐진 실루엣, 내보낸 뒤 다시 연 결과를 비교하는 브라우저 화면
줄무늬 배경은 원래 흰색 덮개 뒤에서는 보이지 않지만 차집합으로 뚫은 구멍을 통해 보입니다. 내보낸 파일을 다시 가져와도 이 구멍이 유지됩니다.

도형과 파일 양쪽에서 결과 확인하기

이 예제에서 합집합은 Path를 반환했고, 차집합은 윤곽 두 개를 가진 CompoundPath를 반환했습니다. 최종 경계는 SVG 단위로 x = 40, y = 40, width = 220, height = 140이었습니다. 아트워크는 300 × 220 내보내기 뷰포트 안에 있으므로 도형 경계와 문서 크기는 의도적으로 다릅니다.

구멍의 중심인 (105, 105)를 확인했습니다. 이 점은 합쳐진 실루엣 안에 있었고 차집합 결과에서는 밖에 있었습니다. 채워진 몸체의 (60, 60) 지점은 계속 안에 있었습니다. 내보낸 SVG를 다시 가져왔을 때도 경계가 유지되었고 구멍 중심은 다시 제외되었습니다. 이는 이 단순한 테스트 자료의 결과이며 모든 가져온 파일을 보장하지는 않습니다.

내보내기 API는 SVG 문자열을 반환하고 명시적인 경계를 받을 수 있습니다. 결과 아래에 표시된 마크업을 result.svg로 복사한 다음 파일을 별도로 여세요. 저장한 내보내기 결과에는 닫힌 하위 경로 두 개를 가진 경로 요소 하나가 포함되었으며, 브라우저에서 직접 열어도 올바르게 렌더링되었습니다.

자신의 아트워크에서는 다음을 확인하세요.

  • 원본과 비교한 실루엣 및 각 구멍
  • 배경이나 숨겨진 보조 도형이 실수로 포함되었는지 여부
  • 원하는 채우기: 합쳐진 도형 하나는 독립적으로 편집 가능한 두 개의 단색 채우기를 유지할 수 없습니다.
  • 내보낸 뷰포트, 특히 아트워크가 문서 가장자리에 닿는 경우
  • 실제로 사용할 애플리케이션에서의 파일 상태

흰색 덮개는 흰 종이 위에서 구멍처럼 보일 수 있습니다. 대비되는 배경 위에 결과를 놓아 투명도를 확인하세요. SVG 구멍이 채워지는 문제 안내는 관련된 복합 경로와 채우기 규칙 문제를 설명합니다.

연산 결과가 잘못된 도형일 때

메서드가 없습니다. 선택한 항목의 클래스를 살펴보세요. 그룹 안에서 원하는 경로를 찾거나 가져오는 동안 지원되는 기본 도형을 변환하세요. 모든 하위 요소를 합치는 방식으로 해결하지 마세요. 복합 경로에도 자식 요소가 있으며 구멍 관계가 중요합니다.

결과가 달라지지 않은 것 같습니다. 반환된 항목을 표시하는지 확인하세요. 원본을 계속 표시하면 성공한 차집합 결과를 가릴 수 있습니다. 이 예제에서는 최종 결과만 활성 레이어에 들어갑니다.

스트로크가 사라지거나 의미가 바뀝니다. 이 예제는 닫힌 채우기 영역을 대상으로 합니다. 눈에 보이는 두꺼운 선이 스트로크가 차지하는 영역과 자동으로 같은 도형이 되는 것은 아닙니다. 그 외곽선을 채워진 피연산자로 사용해야 한다면 벡터 편집기에서 외곽선으로 변환한 사본을 준비하고 가져오기 전에 확인하세요. 편집 가능한 원본은 보관하세요.

세부 요소가 많은 아트워크가 제대로 처리되지 않습니다. 전체 일러스트레이션에 연산을 연속 적용하기 전에 피연산자 두 개를 분리하여 윤곽을 확인하세요. 중복, 자기 교차, 작은 조각은 사례별 확인이 필요합니다. 이 작은 예제는 성능이나 폭넓은 SVG 호환성을 측정하지 않습니다. 한 번의 수정이라면 도형 처리 파이프라인을 작성하는 것보다 벡터 편집기의 선택 및 노드 도구가 더 쉬울 수 있습니다.

소스가 아직 PNG 또는 JPG인 경우

편집 가능한 원본이 없다면 PerfectVector의 이미지 벡터화 작업 흐름으로 적합한 래스터 아트워크에서 SVG를 준비할 수 있습니다. 결과를 미리 보고 윤곽과 빈 공간을 살펴본 뒤 Paper.js에서 테스트할 후보 파일을 다운로드하세요.

벡터화는 프로그램이 어떤 부분을 합치거나 빼야 하는지 식별하지 않습니다. 가져온 구조를 살펴보고 적절한 피연산자를 선택하며 내보낸 결과를 확인해야 합니다. 원본 벡터가 있으면 사용하세요. 단순한 정사각형이나 원은 추적하지 말고 직접 그리세요. 이미지 벡터화 개요는 이러한 소스 파일 선택을 다룹니다.

FAQ

가져온 SVG 그룹에 unite를 호출할 수 있나요? 먼저 그룹 안에서 원하는 Path 또는 CompoundPath 피연산자를 선택하세요. 그룹은 구성 방식을 나타내며 모든 자식 요소를 합치면 배경이 포함되거나 의도한 구분이 사라질 수 있습니다.

subtract는 원본 경로를 제거하나요? 새로운 경로 항목을 반환합니다. 이 예제는 가져오기와 불리언 결과에 insert: false를 사용한 뒤 최종 결과만 삽입합니다. 소스 피연산자는 가져온 컨테이너 아래에 남아 있습니다.

구멍이 여전히 흰색으로 보이는 이유는 무엇인가요? 색이 있는 배경에서 확인하세요. 흰색으로 채워진 객체는 뒤에 있는 것을 가리지만, 차집합으로 만든 구멍은 배경을 드러냅니다. 내보낸 파일을 다시 열어 이 관계가 유지되는지 확인하세요.

벡터화가 불리언 정리 작업도 해 주나요? 아닙니다. 적합한 래스터 소스에서 경로 아트워크를 복원할 수 있지만, 어떤 도형을 합치고 어떤 영역을 제거하며 결과를 어떻게 검증할지는 여전히 애플리케이션에서 결정해야 합니다.

Sources

  1. Paper.js — Project 참조 — SVG 가져오기, 내보내기, 경계, 프로젝트 내용을 설명합니다.
  2. Paper.js — Path 참조 — 합집합과 차집합, 반환되는 경로 항목, 불리언 옵션을 정의합니다.
  3. Paper.js — CompoundPath 참조 — 복합 도형과 이를 구성하는 경로를 설명합니다.

래스터 이미지가 유일한 소스라면 SVG 후보 파일을 준비하고 각 부분을 살펴본 뒤, 나머지 아트워크를 처리하기 전에 필요한 최소 규모의 불리언 연산을 테스트하세요.

블로그의 다른 글

편집하기 쉬운
더 깔끔한 SVG로 다시 시작하세요