PerfectVector
โดย Irene Kimอ่าน 3 นาที

บูลีน SVG ใน Paper.js: ตัดและรวมงานภาพที่นำเข้า

นำเข้าพาธ SVG ใน Paper.js รวมรูปทรงซ้อน ลบพื้นที่ให้เป็นช่องเปิดจริง และตรวจไฟล์ส่งออกด้วยตัวอย่างเบราว์เซอร์เล็กที่ทำซ้ำได้

ในหน้านี้

นำเข้า SVG ค้นหาวัตถุพาธที่ตั้งใจ แล้วเรียก unite() เพื่อรวมพื้นที่เติมหรือ subtract() เพื่อลบพื้นที่หนึ่งจากอีกพื้นที่ เก็บตัวถูกดำเนินการไว้จนตรวจผลแล้ว และเปิด SVG ส่งออกใหม่ก่อนใช้ที่อื่น

การตัดสินใจสำคัญเกิดก่อนการดำเนินการบูลีน: รูปทรงใดควรอยู่ด้วยกัน? กลุ่มนำเข้าอาจมีสี่เหลี่ยมพื้นหลัง พาธตัดภาพ ตัวอักษร และส่วนตกแต่ง การรวมองค์ประกอบย่อยทุกตัวอาจลบการแยกส่วนที่ตั้งใจเก็บ คู่มือนี้ใช้พาธปิดสามพาธที่มีชื่อเพื่อให้เห็นชัดว่าอะไรเปลี่ยน

เริ่มด้วยรูปทรงเติมที่ระบุได้

ตัวนำเข้า SVG ของ Paper.js รับมาร์กอัป SVG องค์ประกอบ SVG หรือ URL วิธีเหล่านั้นต้องจัดการโหลดต่างกัน: ตัวอย่างนี้นำเข้าสตริงอินไลน์ ไฟล์ระยะไกลควรประมวลผลใน callback นำเข้าหลังโหลด

สำหรับงานนี้ ตัวถูกดำเนินการต้องเป็นวัตถุ Path หรือ CompoundPath กลุ่มเป็นคอนเทนเนอร์ และภาพราสเตอร์ไม่มีขอบเขตที่ต้องใช้สำหรับบูลีนพาธ หากไฟล์ทำงานเพียงเหมือนภาพเดียว ให้ตรวจ ทำไม SVG จึงแยกกลุ่มไม่ได้ ก่อน

ใช้ ID สำหรับส่วนที่ควบคุมเอง อย่าสมมติว่า children[0] หมายถึง “โลโก้” ในทุกไฟล์ส่งออก ตรวจงานที่ไม่รู้จักและกำหนดส่วนต่าง ๆ อย่างตั้งใจ เก็บ compound path เดิมไว้ครบเมื่อพาธย่อยกำหนดช่องเปิดที่ต้องการอยู่แล้ว

รันการนำเข้า รวม และลบในตัวอย่างเล็ก

เราทดสอบโค้ดต่อไปนี้ด้วย 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 ที่มีเส้นรอบรูปสองเส้น ขอบเขตสุดท้ายคือ x = 40, y = 40, กว้าง = 220, สูง = 140 ในหน่วย SVG งานอยู่ภายในวิวพอร์ตส่งออก 300 × 220 ดังนั้นขอบเขตกับขนาดเอกสารจึงตั้งใจให้ต่างกัน

เราตรวจศูนย์กลางช่องเปิดที่ (105, 105): อยู่ภายในรูปเงาที่รวมและอยู่นอกผลหลังลบ จุดในตัวรูปทึบที่ (60, 60) ยังอยู่ภายใน การนำเข้า SVG ส่งออกใหม่รักษาขอบเขตและไม่รวมศูนย์กลางช่องเปิดอีกครั้ง นี่เป็นผลของตัวอย่างเรียบง่าย ไม่ใช่คำรับประกันทุกไฟล์นำเข้า

API ส่งออก คืนสตริง SVG และรับขอบเขตชัดเจนได้ คัดลอกมาร์กอัปที่แสดงใต้ผลลง result.svg แล้วเปิดไฟล์แยก ผลส่งออกที่เราบันทึกมีองค์ประกอบพาธเดียวพร้อมพาธย่อยปิดสองส่วน และเรนเดอร์ถูกต้องเมื่อเปิดโดยตรงในเบราว์เซอร์

สำหรับงานของคุณ ตรวจ:

  • รูปเงาและทุกช่องเปิดเทียบต้นฉบับ
  • ว่ามีพื้นหลังหรือรูปช่วยที่ซ่อนถูกนำมารวมโดยไม่ตั้งใจหรือไม่
  • สีเติมที่ตั้งใจ เพราะรูปทรงรวมเดียวรักษาสีแบนสองสีให้แก้อิสระไม่ได้
  • วิวพอร์ตส่งออก โดยเฉพาะเมื่องานไปถึงขอบเอกสาร
  • ไฟล์ในแอปที่จะใช้จริง

วัตถุขาวปิดทับอาจดูเหมือนช่องเปิดบนกระดาษขาว วางผลบนพื้นหลังตัดกันเพื่อตรวจความโปร่งใส คู่มือช่องเปิด SVG ถูกเติม อธิบายปัญหา compound path และกฎเติมที่เกี่ยวข้อง

เมื่อการดำเนินการให้รูปทรงผิด

ไม่มีเมธอด ตรวจคลาสของรายการที่เลือก ค้นหาพาธที่ตั้งใจในกลุ่ม หรือแปลงรูปทรงพื้นฐานที่รองรับระหว่างนำเข้า อย่าแก้ด้วยการรวมองค์ประกอบย่อยทุกระดับ: compound path มีพาธย่อยด้วย และความสัมพันธ์ช่องเปิดสำคัญ

ผลดูไม่เปลี่ยน ยืนยันว่าแสดงรายการที่คืนมา การปล่อยต้นฉบับให้มองเห็นอาจปิดผลลบที่สำเร็จ ในตัวอย่างมีเฉพาะผลสุดท้ายเข้า active layer

เส้นขอบหายหรือความหมายเปลี่ยน ตัวอย่างนี้ทำงานกับพื้นที่ปิดที่เติม เส้นหนาที่เห็นไม่ใช่รูปทรงเดียวกับพื้นที่ที่เส้นขอบครอบคลุมโดยอัตโนมัติ หากต้องการเส้นรอบรูปนั้นเป็นตัวถูกดำเนินการเติม ให้เตรียมสำเนาที่แปลงเส้นขอบเป็นรูปทรงในโปรแกรมเวกเตอร์และตรวจก่อนนำเข้า เก็บต้นฉบับที่แก้ได้

งานละเอียดทำงานไม่ดี แยกตัวถูกดำเนินการสองชิ้นและตรวจเส้นรอบรูปก่อนใช้เป็นลำดับทั่วภาพประกอบ รูปซ้ำ เส้นรอบรูปตัดกันเอง และเศษเล็กต้องตรวจตามกรณี ตัวอย่างเล็กนี้ไม่ได้วัดประสิทธิภาพหรือความเข้ากันได้ SVG กว้าง ๆ สำหรับการซ่อมครั้งเดียว เครื่องมือเลือกและโหนดใน โปรแกรมเวกเตอร์ อาจง่ายกว่าการเขียนกระบวนการรูปทรง

เมื่อต้นฉบับยังเป็น PNG หรือ JPG

หากต้นฉบับที่แก้ได้หาย กระบวนการแปลงภาพเป็นเวกเตอร์ของ PerfectVector ช่วยเตรียม SVG จากงานราสเตอร์ที่เหมาะสมได้ พรีวิวผล ตรวจเส้นรอบรูปและพื้นที่ว่าง แล้วดาวน์โหลดไฟล์สำหรับประเมินใน Paper.js

การแปลงเป็นเวกเตอร์ไม่ได้ระบุว่าส่วนใดโปรแกรมควรรวมหรือลบ คุณยังต้องตรวจโครงสร้างนำเข้า เลือกตัวถูกดำเนินการถูกต้อง และตรวจผลส่งออก ใช้เวกเตอร์เดิมเมื่อมี วาดสี่เหลี่ยมหรือวงกลมเรียบง่ายโดยตรงแทนลากพาธ ภาพรวมการแปลงภาพเป็นเวกเตอร์ ครอบคลุมการเลือกไฟล์ต้นฉบับนั้น

คำถามที่พบบ่อย

เรียก unite บนกลุ่ม SVG ที่นำเข้าได้หรือไม่? เลือกตัวถูกดำเนินการ Path หรือ CompoundPath ที่ตั้งใจภายในกลุ่มก่อน กลุ่มอธิบายการจัดระเบียบ การรวมองค์ประกอบย่อยทุกตัวอาจรวมพื้นหลังหรือทำลายการแยกที่ตั้งใจ

subtract ลบพาธต้นฉบับหรือไม่? มันคืนรายการพาธใหม่ ตัวอย่างนี้ใช้ insert: false สำหรับนำเข้าและผลบูลีน แล้วแทรกเฉพาะผลสุดท้าย ตัวถูกดำเนินการต้นทางยังอยู่ภายในคอนเทนเนอร์นำเข้า

ทำไมช่องเปิดยังดูขาว? ตรวจบนพื้นหลังมีสี วัตถุเติมขาวปิดสิ่งด้านหลัง ส่วนช่องที่ลบเผยพื้นหลัง เปิดไฟล์ส่งออกใหม่เพื่อยืนยันว่าความสัมพันธ์ยังคงอยู่

การแปลงเป็นเวกเตอร์ทำความสะอาดบูลีนให้ไหม? ไม่ มันกู้พาธจากราสเตอร์ที่เหมาะสมได้ แต่แอปยังต้องเลือกว่ารวมรูปทรงใด ลบพื้นที่ใด และตรวจผลอย่างไร

แหล่งอ้างอิง

  1. Paper.js — เอกสารอ้างอิง Project — อธิบายการนำเข้า SVG ส่งออก ขอบเขต และเนื้อหาโปรเจกต์
  2. Paper.js — เอกสารอ้างอิง Path — นิยามการรวมและลบ รายการพาธที่คืนมา และตัวเลือกบูลีน
  3. Paper.js — เอกสารอ้างอิง CompoundPath — อธิบายรูปทรงประกอบและพาธส่วนย่อย

หากมีเพียงภาพราสเตอร์เป็นต้นฉบับ ให้ เตรียม SVG สำหรับประเมิน ตรวจส่วนต่าง ๆ แล้วทดสอบการดำเนินการบูลีนเล็กที่สุดที่มีประโยชน์ก่อนประมวลผลงานส่วนที่เหลือ

เพิ่มเติมจากบล็อก

เริ่มต้นด้วย SVG ที่เรียบร้อยขึ้น
และแก้ไขได้ง่ายกว่า