PerfectVector
Bởi Irene Kim9 phút đọc

Phép Boolean SVG trong Paper.js: Cắt và ghép hình nhập

Nhập đường dẫn SVG vào Paper.js, ghép các hình chồng lấp, trừ một lỗ thật và kiểm tra tệp xuất bằng ví dụ trình duyệt nhỏ có thể tái lập.

Trên trang này

Nhập SVG, tìm các đối tượng đường dẫn mong muốn, rồi gọi unite() để ghép vùng có màu tô hoặc subtract() để loại vùng này khỏi vùng khác. Giữ các toán hạng đến khi kiểm tra kết quả, và mở lại SVG xuất ra trước khi dùng ở nơi khác.

Quyết định quan trọng nằm trước phép Boolean: những hình nào thuộc về nhau? Nhóm nhập vào có thể chứa hình chữ nhật nền, đường dẫn cắt, chữ và phần trang trí. Kết hợp mọi phần tử con có thể xóa những phân tách bạn muốn giữ. Hướng dẫn này dùng ba đường dẫn khép kín có tên để bạn thấy chính xác thay đổi.

Bắt đầu với hình học có màu tô dễ nhận diện

Công cụ nhập SVG của Paper.js nhận mã SVG, phần tử SVG hoặc URL. Những cách đó cần xử lý tải khác nhau: ví dụ này nhập chuỗi nội tuyến; tệp từ xa nên được xử lý trong hàm gọi lại nhập sau khi tải.

Với nhiệm vụ này, toán hạng phải là đối tượng Path hoặc CompoundPath. Nhóm là phần tử chứa, còn ảnh raster không cung cấp ranh giới cần cho phép Boolean đường dẫn. Nếu tệp chỉ hoạt động như một ảnh duy nhất, trước hết kiểm tra vì sao SVG không tách nhóm được.

Dùng ID cho những phần bạn kiểm soát. Đừng mặc định children[0] nghĩa là “logo” trong mọi bản xuất. Kiểm tra hình chưa biết và chủ động chỉ định các phần. Giữ nguyên đường dẫn phức hợp hiện có khi các đường dẫn con đã xác định đúng các lỗ.

Chạy ví dụ nhỏ về nhập, hợp và trừ

Chúng tôi thử mã sau với Paper.js 0.12.18 trong trình duyệt. Hình là SVG gốc viết thủ công: thân vuông, tai chồng lấp và ô vuông trắng đánh dấu lỗ dự định. Nó không phải mẫu chuyển đổi PerfectVector.

Trong thư mục trống, cài thư viện với phiên bản cố định:

npm install --save-exact paper@0.12.18

Lưu đoạn này thành 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>

Lưu đoạn này thành example.js, rồi mở HTML trong trình duyệt:

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;

Nội dung nhập ở ngoài cảnh với insert: false. expandShapes: true yêu cầu công cụ nhập chuyển các hình cơ bản được hỗ trợ thành đường dẫn; mẫu của chúng tôi đã chứa phần tử đường dẫn. Kiểm tra kiểu đối tượng tường minh vẫn quan trọng vì ID nhập vào có thể chỉ phần tử chứa hoặc loại đối tượng khác.

API Boolean trả về đối tượng đường dẫn mới. Ở đây, kết quả được giữ ngoài cảnh đến khi thêm hình cắt cuối. Các phần gốc vẫn có dưới imported, nên thao tác thất bại không đòi tái dựng nguồn.

joined.subtract(hole) loại lỗ khỏi hình bao đã ghép. Đảo toán hạng là đặt câu hỏi khác và có thể cho kết quả rỗng hoặc bất ngờ. Chế độ trừ mặc định của Paper.js coi toán hạng là vùng diện tích. Tùy chọn trace liên quan đến hình học Boolean; không liên quan đến đồ lại PNG thành vector.

So sánh trình duyệt ba đường dẫn SVG nhập vào, hình bao đã ghép có lỗ vuông trong suốt và kết quả xuất được mở lại
Nền sọc vẫn bị mảng trắng gốc che và hiện qua lỗ đã trừ. Bản xuất giữ lỗ đó khi nhập lại.

Kiểm tra kết quả như hình học và như tệp

Trong ví dụ này, phép hợp trả về Path; phép trừ trả về CompoundPath với hai đường bao. Giới hạn cuối là x = 40, y = 40, chiều rộng = 220, chiều cao = 140 theo đơn vị SVG. Hình nằm trong khung nhìn xuất 300 × 220, nên giới hạn hình và kích thước tài liệu khác nhau có chủ đích.

Chúng tôi kiểm tra tâm lỗ tại (105, 105): nó nằm trong hình bao đã ghép và ngoài kết quả đã trừ. Điểm trong thân đặc tại (60, 60) vẫn nằm trong. Nhập lại SVG xuất ra giữ giới hạn và một lần nữa loại tâm lỗ. Đây là kết quả cho mẫu đơn giản này, không bảo đảm cho mọi tệp nhập.

API xuất có thể trả chuỗi SVG và nhận giới hạn rõ ràng. Sao chép mã hiển thị dưới kết quả vào result.svg, rồi mở riêng tệp đó. Bản xuất đã lưu của chúng tôi chứa một phần tử đường dẫn với hai đường dẫn con khép kín; nó cũng hiển thị đúng khi mở trực tiếp trong trình duyệt.

Với hình của bạn, kiểm tra:

  • hình bao và từng lỗ so với bản gốc;
  • nền hay hình phụ ẩn có vô tình bị đưa vào không;
  • màu tô mong muốn, vì một hình đã ghép không giữ được hai màu phẳng chỉnh sửa độc lập;
  • khung nhìn xuất, nhất là khi hình chạm mép tài liệu;
  • tệp trong ứng dụng thực sự sẽ sử dụng nó.

Lớp phủ trắng có thể trông như lỗ trên giấy trắng. Đặt kết quả trên nền tương phản để kiểm tra độ trong suốt. Hướng dẫn lỗ SVG bị lấp giải thích vấn đề liên quan đến đường dẫn phức hợp và quy tắc tô màu.

Khi thao tác tạo hình sai

Thiếu phương thức. Kiểm tra kiểu của đối tượng được chọn. Tìm đường dẫn cần thiết trong nhóm hoặc chuyển các hình cơ bản được hỗ trợ khi nhập. Đừng giải quyết bằng cách kết hợp mọi phần tử hậu duệ: đường dẫn phức hợp cũng chứa phần tử con, và quan hệ lỗ của chúng quan trọng.

Kết quả trông không đổi. Bảo đảm bạn hiển thị đối tượng được trả về. Để các bản gốc hiện có thể che phép trừ thành công. Trong ví dụ, chỉ kết quả cuối vào lớp đang hoạt động.

Đường viền biến mất hoặc đổi ý nghĩa. Ví dụ này thao tác trên vùng khép kín có màu tô. Đường dày nhìn thấy không tự là cùng hình với vùng mà đường viền của nó quét qua. Nếu cần đường viền đó làm toán hạng có màu tô, chuẩn bị bản sao đã chuyển viền thành hình trong trình chỉnh sửa vector và kiểm tra trước khi nhập. Giữ bản gốc chỉnh sửa được.

Hình nhiều chi tiết hoạt động kém. Tách hai toán hạng và kiểm tra đường bao trước khi áp dụng một chuỗi thao tác lên cả hình minh họa. Bản trùng, tự giao và mảnh rất nhỏ cần kiểm tra theo trường hợp. Ví dụ nhỏ này không đo hiệu năng hay tương thích SVG rộng. Với sửa chữa một lần, công cụ chọn và chỉnh nút trong trình chỉnh sửa vector có thể dễ hơn viết quy trình hình học.

Khi nguồn vẫn là PNG hoặc JPG

Nếu mất bản gốc chỉnh sửa được, quy trình ảnh sang vector của PerfectVector có thể giúp chuẩn bị SVG từ hình raster phù hợp. Xem trước kết quả, kiểm tra đường bao và không gian âm, rồi tải bản để thử trong Paper.js.

Vector hóa không nhận diện phần nào chương trình của bạn nên hợp hoặc trừ. Bạn vẫn cần kiểm tra cấu trúc nhập vào, chọn đúng toán hạng và kiểm tra kết quả xuất. Dùng vector gốc khi có; vẽ trực tiếp hình vuông hoặc tròn đơn giản thay vì đồ lại. Tổng quan vector hóa ảnh trình bày quyết định về tệp nguồn đó.

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

Tôi có thể gọi unite trên nhóm SVG nhập vào không? Trước hết chọn các toán hạng Path hoặc CompoundPath mong muốn trong nhóm. Nhóm mô tả tổ chức, và kết hợp mọi phần tử con có thể đưa nền vào hoặc phá phân tách dự định.

subtract có xóa đường dẫn gốc không? Nó trả về đối tượng đường dẫn mới. Ví dụ này dùng insert: false cho nội dung nhập và kết quả Boolean, rồi chỉ chèn kết quả cuối. Các toán hạng nguồn vẫn có trong phần tử chứa được nhập.

Vì sao lỗ vẫn trông trắng? Kiểm tra trên nền màu. Đối tượng tô trắng che những gì phía sau; lỗ đã trừ để lộ nền đó. Mở lại tệp xuất để xác nhận quan hệ còn giữ.

Vector hóa có làm phần dọn Boolean thay tôi không? Không. Nó có thể khôi phục hình đường dẫn từ nguồn raster phù hợp, nhưng ứng dụng của bạn vẫn phải chọn hình học cần ghép, vùng cần loại và cách xác minh kết quả.

Nguồn tham khảo

  1. Paper.js — Tài liệu Project — Mô tả nhập, xuất SVG, giới hạn và nội dung dự án.
  2. Paper.js — Tài liệu Path — Định nghĩa hợp và trừ, đối tượng đường dẫn được trả về và tùy chọn Boolean.
  3. Paper.js — Tài liệu CompoundPath — Mô tả hình học phức hợp và các đường dẫn cấu thành.

Nếu ảnh raster là nguồn duy nhất, hãy chuẩn bị một bản SVG để đánh giá, kiểm tra các phần, rồi thử phép Boolean nhỏ nhất hữu ích trước khi xử lý phần hình còn lại.

Thêm từ blog

Bắt đầu với SVG gọn sạch hơn
và dễ chỉnh sửa hơn