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

หน่วย ClipPath ของ SVG: จัดรูปทรงที่สร้างเองให้พอดีกับเป้าหมาย

เลือกหน่วย clipPath ของ SVG ปรับพิกัดรูปเงาเป็นมาตรฐาน และรักษาสัดส่วน ทดสอบเป้าหมายกว้างและสูงโดยคงช่องเปิดและรูปทรงต้นฉบับไว้

ในหน้านี้

ใช้ clipPathUnits="objectBoundingBox" เมื่อรูปทรงตัดภาพควรยืดตามขอบเขตของเป้าหมาย ปรับพิกัดรูปทรงเป็นมาตรฐานก่อน ใช้ userSpaceOnUse เมื่อต้องการวางตำแหน่งอย่างชัดเจนหรือปรับมาตราส่วนเท่ากันเพื่อรักษาสัดส่วนรูปทรง

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

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

เลือกระบบพิกัดก่อนปรับขนาด

ค่าปริยายคือ userSpaceOnUse พิกัดตัดภาพของมันอยู่ในระบบพิกัดผู้ใช้ขององค์ประกอบที่อ้างอิงพื้นที่ตัดภาพ เมื่อใช้ objectBoundingBox ขอบบนซ้ายของเป้าหมายแมปเป็น (0, 0) และขอบล่างขวาแมปเป็น (1, 1) ดู เอกสารอ้างอิง clipPathUnits

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

กรอบครอบเป้าหมายไม่จำเป็นต้องเป็น viewBox ของ SVG ด้านนอก การตัดภาพกลุ่มใช้ขอบเขตของกลุ่มนั้น ซึ่งอาจต่างจากสี่เหลี่ยมภายในกลุ่ม สำหรับการทดสอบแรกที่คาดการณ์ได้ ให้ใช้พื้นที่ตัดภาพกับสี่เหลี่ยมที่รู้ขนาดโดยตรง

เปรียบเทียบเป้าหมายกว้างกับเป้าหมายสูง

ขอบเขตภายนอกของที่คั่นหนังสือของเราคือ x=20, y=10, width=100, height=100 รูปข้าวหลามตัดเป็นพาธย่อยที่สองภายในพาธเดียวกัน การทดสอบใช้มันกับสี่เหลี่ยมขนาด 200 × 120 และ 120 × 200 ในหน่วย SVG เฉพาะตัว

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

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

บันทึกตัวอย่างฉบับเต็มด้านล่างเป็น clippath-comparison.svg แล้วเปิดในเบราว์เซอร์ คอลัมน์เรียงตามภาพ แถวบนใช้สี่เหลี่ยมกว้าง แถวล่างใช้สี่เหลี่ยมสูง การเลื่อนเพื่อแสดงผลจัดวางตัวอย่างและไม่ได้เปลี่ยนขนาดเป้าหมายในพิกัดเฉพาะตัว

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 470">
  <defs>
    <path id="silhouette" d="M20 10H120V110L70 85L20 110Z M70 30L85 45L70 60L55 45Z"/>
    <clipPath id="fixed" clipPathUnits="userSpaceOnUse">
      <use href="#silhouette" clip-rule="evenodd"/>
    </clipPath>
    <clipPath id="box" clipPathUnits="objectBoundingBox">
      <use href="#silhouette" clip-rule="evenodd"
        transform="matrix(.01 0 0 .01 -.2 -.1)"/>
    </clipPath>
    <clipPath id="wide-fit" clipPathUnits="userSpaceOnUse">
      <use href="#silhouette" clip-rule="evenodd"
        transform="matrix(1.2 0 0 1.2 16 -12)"/>
    </clipPath>
    <clipPath id="tall-fit" clipPathUnits="userSpaceOnUse">
      <use href="#silhouette" clip-rule="evenodd"
        transform="matrix(1.2 0 0 1.2 -24 28)"/>
    </clipPath>
  </defs>
  <g fill="#107c86">
    <rect x="0" y="0" width="200" height="120"
      transform="translate(20 30)" clip-path="url(#fixed)"/>
    <rect x="0" y="0" width="200" height="120"
      transform="translate(260 30)" clip-path="url(#box)"/>
    <rect x="0" y="0" width="200" height="120"
      transform="translate(500 30)" clip-path="url(#wide-fit)"/>
    <rect x="0" y="0" width="120" height="200"
      transform="translate(60 230)" clip-path="url(#fixed)"/>
    <rect x="0" y="0" width="120" height="200"
      transform="translate(300 230)" clip-path="url(#box)"/>
    <rect x="0" y="0" width="120" height="200"
      transform="translate(540 230)" clip-path="url(#tall-fit)"/>
  </g>
</svg>

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

ปรับขอบเขตต้นฉบับเป็นมาตรฐาน รวมทั้งจุดกำเนิด

สำหรับจุด (x, y) ในต้นฉบับที่มีขอบเขต (minX, minY, width, height) ให้คำนวณ:

normalizedX = (x - minX) / width
normalizedY = (y - minY) / height

ในที่นี้คือ (x - 20) / 100 และ (y - 10) / 100 เมทริกซ์ในคำจำกัดความ box ทำทั้งสองการคำนวณโดยไม่ต้องเขียนข้อมูลพาธใหม่:

matrix(0.01 0 0 0.01 -0.2 -0.1)

มันแมป (20, 10) เป็น (0, 0) และ (120, 110) เป็น (1, 1) การหารด้วย 100 โดยไม่ลบจุดกำเนิดจะทำให้รูปทรงยังเยื้องอยู่ภายในเป้าหมาย จากนั้นการแมปกรอบครอบจะปรับมาตราส่วนผลที่ทำเป็นมาตรฐานแยกตามความกว้างและความสูงเป้าหมาย

ใช้ขอบเขตจริงของรูปทรงที่ต้องการปรับเป็นมาตรฐาน viewBox อาจรวมพื้นที่ว่างที่ตั้งใจเว้นไว้ ขนาดจึงไม่จำเป็นต้องเท่าขอบเขตรูปเงา หากต้องการเก็บพื้นที่ว่างนั้น ให้เลือกใช้สี่เหลี่ยม viewBox อย่างตั้งใจแทนการเผลอผสมค่าที่วัดสองแบบ

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

รักษาสัดส่วนด้วยตัวคูณมาตราส่วนเดียว

สำหรับสี่เหลี่ยมเป้าหมายที่อยู่ ณ (0, 0) ในพิกัดเฉพาะตัว มีความกว้าง W และความสูง H ให้ใช้:

s  = min(W / width, H / height)
tx = (W - s * width) / 2 - s * minX
ty = (H - s * height) / 2 - s * minY
matrix(s 0 0 s tx ty)

เป้าหมายกว้างให้ s=1.2, tx=16 และ ty=-12 พื้นที่ตัดภาพอยู่ที่ x=40..160 และ y=0..120 เป้าหมายสูงให้ s=1.2, tx=-24 และ ty=28 วางพื้นที่ตัดภาพที่ x=0..120 และ y=40..160

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

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

เก็บช่องเปิดไว้ในรูปทรงตัดภาพ

ตัวอย่างวาง clip-rule="evenodd" บน use แต่ละตัวภายใน clipPath ของมัน พาธที่อ้างอิงมีทั้งขอบที่คั่นหนังสือและพาธย่อยข้าวหลามตัด กฎนี้กำหนดว่าพื้นที่ใดของรูปทรงประกอบอยู่ภายในพื้นที่ตัดภาพ

การวาง clip-rule บนสี่เหลี่ยมสีเขียวอมฟ้าไม่ได้กำหนดกฎของรูปทรงตัดภาพ เช่นเดียวกัน fill-rule ที่ใช้ระบายสีต้นฉบับไม่ใช่สิ่งทดแทนกฎตัดภาพ เอกสารอ้างอิง clip-rule ของ MDN อธิบายขอบเขตการใช้ภายใน clipPath

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

หากงานต้องการขอบโปร่งใสบางส่วนหรือการมองเห็นตามความสว่าง ให้ เปรียบเทียบ clipPath กับมาสก์ SVG บนภาพเดียวกัน พื้นที่ตัดภาพเหมาะกับขอบเขตเรขาคณิต ส่วนมาสก์ให้รูปแบบควบคุมการมองเห็นอีกแบบ สำหรับไอคอนสีเดียวที่ระบายผ่าน CSS ดู คู่มือมาสก์ SVG ใน CSS

ตรวจขอบเขตและผลส่งออก

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

ก่อนส่งมอบ:

  1. ยืนยันว่า ID พื้นที่ตัดภาพที่อ้างอิงมีอยู่และไม่ซ้ำในเอกสาร
  2. เปรียบเทียบเป้าหมายกว้างกับสูง รวมทั้งช่องเปิดเล็กที่สุด
  3. ตรวจทั้งขอบเขตต้นฉบับและขอบเขตเป้าหมายในระบบพิกัดที่ตั้งใจใช้
  4. บันทึกแล้วเปิด SVG ที่ส่งออกอีกครั้งในแอปพลิเคชันที่จะใช้ไฟล์
  5. เก็บรูปทรงต้นฉบับไว้เมื่อพื้นที่ตัดภาพต้องยังแก้ไขได้

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

กู้คืนรูปเงาราสเตอร์เมื่อจำเป็น

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

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

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

objectBoundingBox รักษาสัดส่วนรูปทรงหรือไม่? ไม่ มันแมปพื้นที่ตัดภาพที่ปรับเป็นมาตรฐานไปยังความกว้างและความสูงเป้าหมายแยกกัน ใช้มาตราส่วนเท่ากันใน userSpaceOnUse เมื่อรูปเงาต้องรักษาสัดส่วน

ทำไมเปลี่ยน clipPathUnits แล้วรูปทรงหายไป? พิกัดพาธอาจยังเป็นหน่วยต้นฉบับ ปรับเป็นมาตรฐานในระบบพิกัดที่อ้างอิงเป้าหมาย รวมทั้งจุดกำเนิดต้นฉบับ หรือคง userSpaceOnUse แล้ววางตำแหน่งอย่างชัดเจน

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

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

  1. MDN — clipPathUnits — ตัวเลือกพิกัดและการตีความพื้นที่ผู้ใช้ที่เป็นค่าปริยาย
  2. MDN — clip-rule — ตำแหน่งกฎทิศทางวนภายในพาธตัดภาพ
  3. W3C — ระบบพิกัด SVG — การแมปกรอบครอบ การไม่รวมเส้นขอบ และข้อจำกัดมิติศูนย์
  4. W3C — CSS Masking — รูปทรงตัดภาพ รูปเงาที่รวมกัน และพาธพื้นฐานที่ไม่เปลี่ยน

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

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

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