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

เงา SVG ถูกตัด? ตรวจฟิลเตอร์และวิวพอร์ต

แก้เงา SVG ที่ถูกตัดด้วยการตรวจสองขอบเขตแยกกัน: พื้นที่ฟิลเตอร์และวิวพอร์ตด้านนอก ทำตามตัวอย่างที่ทดสอบแล้วก่อนเปลี่ยนพาธ

ในหน้านี้

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

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

วินิจฉัยขอบก่อนเปลี่ยนงานภาพ

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

สองขอบเขตกับพาธเดียวที่ไม่เปลี่ยน

เราสร้างรูปเงาเล็กด้วยมือและเปิดสามเวอร์ชันในเบราว์เซอร์ แต่ละเวอร์ชันใช้พาธและการตั้งค่า feDropShadow เดียวกัน: dx="22", dy="18" และ stdDeviation="12" ภาพด้านล่างแสดงการเรนเดอร์เบราว์เซอร์จริง ไม่ใช่ผลแปลง PerfectVector

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

ในเวอร์ชันแรก พื้นที่ฟิลเตอร์เริ่มจาก (50, 50) ถึง (210, 180) ทำให้เงาถูกตัดเป็นขอบแข็งทางขวาและล่าง ในเวอร์ชันที่สอง พื้นที่ขยายครอบคลุม (-20, -20) ถึง (300, 280) แต่ SVG ยังแสดงเพียง 0 0 240 220 ขอบขวาของเงาจึงไปถึงกรอบวิวพอร์ตและถูกตัดที่นั่น

เวอร์ชันที่สามคงพื้นที่ฟิลเตอร์ใหญ่กว่าและเปลี่ยน viewBox เป็น -20 -20 320 300 ค่า width และ height เปลี่ยนเป็น 320 และ 300 ด้วย เพื่อให้ตัวอย่างทั้งสามยังมีหนึ่งหน่วย SVG ต่อหนึ่งพิกเซล CSS พื้นที่เพิ่มรองรับเงาที่มองเห็นโดยไม่ปรับขนาดพาธ

ขยายพื้นที่ฟิลเตอร์ในระบบพิกัดที่ถูกต้อง

แอตทริบิวต์ x, y, width และ height ของ <filter> กำหนดพื้นที่ฟิลเตอร์ ค่าปริยายคือ -10%, -10%, 120% และ 120% มีพื้นที่เผื่ออยู่แล้วบางส่วน แต่อาจไม่พอสำหรับระยะเลื่อนและความเบลอเฉพาะนั้น MDN อธิบายค่าปริยายเหล่านี้

ตรวจ filterUnits ก่อนเปลี่ยนตัวเลข:

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

กฎเหล่านี้ใช้กับพื้นที่ฟิลเตอร์ตามคำอธิบายใน เอกสารอ้างอิง filterUnits ไม่ได้เปลี่ยนหน่วยระยะเลื่อนหรือความเบลอของเงาโดยอัตโนมัติ

primitiveUnits ควบคุมค่าความยาวภายในองค์ประกอบพื้นฐานฟิลเตอร์ ค่าปริยายคือ userSpaceOnUse เราตั้งไว้อย่างชัดเจนในตัวอย่างเพื่อให้ 22, 18 และ 12 คงความหมายนั้น การเปลี่ยนเป็น objectBoundingBox จะเปลี่ยนวิธีตีความค่าเหล่านี้ MDN แยกหน่วยองค์ประกอบพื้นฐานออกจากหน่วยพื้นที่ฟิลเตอร์

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

ให้พื้นที่วิวพอร์ต SVG ด้วย

บันทึกตัวอย่างฉบับเต็มนี้เป็น shadow.svg แล้วเปิดในเบราว์เซอร์ นี่คือ SVG ไฟล์จริงที่ใช้สำหรับสถานะที่สาม และตรวจเป็นไฟล์เดี่ยวด้วย:

<svg xmlns="http://www.w3.org/2000/svg" width="320" height="300" viewBox="-20 -20 320 300" overflow="hidden">
  <defs>
    <filter id="shadow" filterUnits="userSpaceOnUse"
      primitiveUnits="userSpaceOnUse" x="-20" y="-20" width="320" height="300">
      <feDropShadow dx="22" dy="18" stdDeviation="12"
        flood-color="#152b34" flood-opacity="0.7"/>
    </filter>
  </defs>
  <path d="M 60 160 L 60 100 Q 60 60 100 60 L 200 60 L 200 120 Q 200 170 150 170 L 70 170 Q 60 170 60 160 Z" fill="#078875" filter="url(#shadow)"/>
</svg>

viewBox มีสี่ค่า: x ต่ำสุด y ต่ำสุด ความกว้าง และความสูง มันแมปสี่เหลี่ยมพิกัดผู้ใช้นั้นไปยังวิวพอร์ต SVG การเพิ่มขนาด viewBox โดยคงความกว้างและสูงที่แสดงเดิมทำให้งานภาพดูเล็กลง ไม่ได้เพิ่มพื้นที่เลย์เอาต์นอกองค์ประกอบ MDN อธิบายการแมป viewBox

หากต้องการทำซ้ำปัญหาทั้งสอง เปลี่ยนเฉพาะค่าเหล่านี้ในสำเนาตัวอย่าง:

  1. สำหรับสถานะกลาง คงฟิลเตอร์เดิมแต่ตั้งรากเป็น width="240", height="220" และ viewBox="0 0 240 220"
  2. สำหรับสถานะแรก คงวิวพอร์ตเล็กนั้นและตั้งฟิลเตอร์เป็น x="50", y="50", width="160" และ height="130" ด้วย
  3. คืนตัวอย่างฉบับเต็มแล้วเปรียบเทียบขอบขวากับล่าง ข้อมูลพาธไม่เปลี่ยนเลย

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

ทำไม overflow จึงช่วย SVG แบบอินไลน์แต่ไม่แก้ปัญหาไฟล์

ตัวอย่างตั้ง overflow="hidden" อย่างชัดเจนเพื่อให้ทำซ้ำขอบเขตวิวพอร์ตได้ สำหรับ SVG แบบอินไลน์ overflow="visible" ลบการตัดตามวิวพอร์ตนั้นได้ แต่ไม่อาจกู้พิกเซลที่ถูกทิ้งจากพื้นที่ฟิลเตอร์ไปแล้ว และองค์ประกอบที่ครอบอยู่ซึ่งมีการตัดภาพของตัวเองยังซ่อนผลได้ CSS เขียนทับแอตทริบิวต์การแสดง SVG ได้ด้วย เอกสารอ้างอิง overflow ของ SVG อธิบายกฎตัดภาพเหล่านี้

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

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

รักษารูปทรงและสร้างเอฟเฟกต์ใหม่แยกกัน

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

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

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

ตรวจไฟล์ที่ส่งมอบ

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

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

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

ทำไมเงายังถูกตัดหลังเพิ่มความกว้างฟิลเตอร์? วิวพอร์ต SVG คอนเทนเนอร์แม่ พาธตัดภาพ หรือมาสก์อาจกำหนดอีกขอบเขต ตรวจ x กับ y ของฟิลเตอร์รวมทั้งความกว้างและสูง แล้วตรวจว่าขอบตัดที่เหลือตรงกับอะไร

filterUnits เปลี่ยนรัศมีเบลอหรือไม่? filterUnits ควบคุมระบบพิกัดพื้นที่ฟิลเตอร์ ส่วน primitiveUnits ควบคุมค่าความยาวภายในองค์ประกอบพื้นฐานฟิลเตอร์ รวมทั้งการตั้งค่าระยะเลื่อนและความเบลอของเงา แยกทั้งสองเมื่อวินิจฉัยไฟล์

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

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

  1. MDN: องค์ประกอบ filter — นิยามองค์ประกอบฟิลเตอร์และพื้นที่เผื่อปริยาย
  2. MDN: filterUnits — อธิบายพิกัดกรอบครอบและพื้นที่ผู้ใช้สำหรับพื้นที่ฟิลเตอร์
  3. MDN: primitiveUnits — แยกความยาวองค์ประกอบพื้นฐานจากพื้นที่ฟิลเตอร์ด้านนอก
  4. MDN: viewBox — อธิบายการแมปพิกัดผู้ใช้ไปยังวิวพอร์ต SVG ที่มองเห็น
  5. MDN: overflow — อธิบายการตัดตามวิวพอร์ต ค่าปริยาย SVG แบบอินไลน์ และลำดับความสำคัญ CSS

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

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

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