การจัดการการโต้ตอบ SVG ด้วยคุณสมบัติเหตุการณ์ตัวชี้

เผยแพร่แล้ว: 2022-03-10
สรุปโดยย่อ ↬ มาดูวิธีการกำหนดรูปแบบการโต้ตอบของรูปภาพ SVG ซึ่งก็คือควบคุมส่วนต่างๆ ของเอกสารที่สามารถรับการคลิก สัมผัส หรือแตะได้โดยใช้คุณสมบัติ pointer-events

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

ดู Pen Amethyst โดย Tiffany Brown (@webinista) บน CodePen

ดู Pen Amethyst โดย Tiffany Brown (@webinista) บน CodePen

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

ฉันหันไปใช้ข้อกำหนด SVG เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับสิ่งที่อาจเกิดขึ้นและดูว่า SVG มีการแก้ไขหรือไม่ คำตอบ: pointer-events

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

เพื่อไม่ให้สับสนกับเหตุการณ์ตัวชี้ DOM ( D ocument O bject M odel) เหตุการณ์ pointer-events เป็นทั้งคุณสมบัติ CSS และแอตทริบิวต์องค์ประกอบ SVG ด้วยสิ่งนี้ เราสามารถจัดการได้ว่าส่วนใดของเอกสารหรือองค์ประกอบ SVG ที่สามารถรับเหตุการณ์จากอุปกรณ์ชี้ตำแหน่ง เช่น เมาส์ แทร็คแพด หรือนิ้ว

หมายเหตุเกี่ยวกับคำศัพท์: "เหตุการณ์ตัวชี้" ยังเป็นชื่อของคุณลักษณะแพลตฟอร์มเว็บที่ไม่เชื่อเรื่องพระเจ้าสำหรับอุปกรณ์สำหรับการป้อนข้อมูลของผู้ใช้ อย่างไรก็ตาม ในบทความนี้ — และสำหรับวัตถุประสงค์ของคุณสมบัติ pointer-events — วลี "pointer events" ยังรวมถึงเหตุการณ์เมาส์และการสัมผัสด้วย

นอกกรอบ: “Shape Model” ของ SVG

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

หมายเหตุ : การเพิ่ม clip-path ไปยังองค์ประกอบแบบโต้ตอบจะเปลี่ยนขอบเขตการโต้ตอบ กล่าวอีกนัยหนึ่ง หากคุณเพิ่ม clip-path รูปหกเหลี่ยมให้ a องค์ประกอบ เฉพาะจุดภายในเส้นทางการคลิปเท่านั้นที่จะคลิกได้ ในทำนองเดียวกัน การเพิ่มการแปลงแบบเบ้จะเปลี่ยนรูปสี่เหลี่ยมให้เป็นสี่เหลี่ยมขนมเปียกปูน

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

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

ทาสีกับองค์ประกอบที่มองเห็นได้

องค์ประกอบ SVG สามารถ "เติม" ได้ แต่ยังสามารถ "ขีด" ได้อีกด้วย เติม หมายถึงการตกแต่งภายในของรูปร่าง โรคหลอดเลือดสมอง หมายถึงเค้าร่างของมัน

เมื่อรวมกันแล้ว "เติม" และ "จังหวะ" เป็นการลง สี ที่แสดงองค์ประกอบไปยังหน้าจอหรือหน้า (หรือที่เรียกว่า ผืนผ้าใบ ) เมื่อเราพูดถึง องค์ประกอบที่ทาสี เราหมายความว่าองค์ประกอบนั้นมีการเติมและ/หรือเส้นขีด โดยปกติแล้ว นี่หมายความว่าองค์ประกอบนั้นยังมองเห็นได้

อย่างไรก็ตาม องค์ประกอบ SVG สามารถทาสีได้โดยไม่ต้องมองเห็น สิ่งนี้อาจเกิดขึ้นได้หากค่าแอตทริบิวต์ที่ visible หรือคุณสมบัติ CSS ถูก hidden หรือเมื่อ none display องค์ประกอบอยู่ที่นั่นและใช้พื้นที่ทางทฤษฎี เรามองไม่เห็นมัน (และเทคโนโลยีอำนวยความสะดวกอาจตรวจไม่พบ)

บางทีอาจทำให้สับสนมากขึ้น องค์ประกอบยังสามารถมองเห็นได้ — นั่นคือ มีค่าการมองเห็นที่คำนวณเป็น visibility visible — โดยไม่ต้องทาสี สิ่งนี้จะเกิดขึ้นเมื่อองค์ประกอบขาดทั้งจังหวะและการเติม

หมายเหตุ : ค่าสีที่มีความโปร่งใสของอัลฟา (เช่น rgba(0,0,0,0) ) จะไม่มีผลกับองค์ประกอบที่ทาสีหรือมองเห็นได้ กล่าวอีกนัยหนึ่ง หากองค์ประกอบมีการเติมหรือเส้นขีดแบบโปร่งใสของอัลฟ่า องค์ประกอบนั้นจะถูกทาสีแม้ว่าจะมองไม่เห็นก็ตาม

การรู้ว่าเมื่อใดที่องค์ประกอบถูกทาสี มองเห็นได้ หรือไม่มีความสำคัญต่อการทำความเข้าใจผลกระทบของแต่ละค่าของ pointer-events

ทั้งหมดหรือไม่มีหรือบางอย่างในระหว่าง: ค่านิยม

pointer-events เป็นทั้งคุณสมบัติ CSS และแอตทริบิวต์องค์ประกอบ SVG ค่าเริ่มต้นคือ auto ซึ่งหมายความว่าเฉพาะส่วนที่ทาสีและมองเห็นได้เท่านั้นที่จะได้รับเหตุการณ์ตัวชี้ ค่าอื่นๆ ส่วนใหญ่สามารถแบ่งออกเป็นสองกลุ่ม:

  1. ค่าที่ต้องการองค์ประกอบเพื่อให้มองเห็นได้ และ
  2. ค่าที่ไม่.

painted , fill , stroke และ all จัดอยู่ในประเภทหลัง คู่หูที่ขึ้นอยู่กับการมองเห็นของพวกเขา - visiblePainted , visibleFill , visibleStroke และ visible - ตกอยู่ในอดีต

ข้อมูลจำเพาะ SVG 2.0 ยังกำหนด bounding-box อีกด้วย เมื่อค่าของ pointer-events เป็น bounding-box พื้นที่สี่เหลี่ยมรอบๆ องค์ประกอบสามารถรับ pointer events ได้เช่นกัน ในขณะที่เขียนนี้ เฉพาะ Chrome 65+ เท่านั้นที่รองรับ bounding-box

none ยังเป็นค่าที่ถูกต้อง ป้องกันไม่ให้องค์ประกอบและลูกของมันได้รับเหตุการณ์ตัวชี้ใด ๆ คุณสมบัติ CSS ของ pointer-events สามารถใช้กับองค์ประกอบ HTML ได้เช่นกัน แต่เมื่อใช้กับ none ค่าที่ถูกต้องคือค่า auto เท่านั้น

เนื่องจากค่าของ pointer-events แสดงให้เห็นได้ดีกว่าที่อธิบาย เรามาดูตัวอย่างกัน

ที่นี่เรามีวงกลมที่มีการเติมและเส้นขีด มีทั้ง ทาสี และ มองเห็นได้ วงกลมทั้งหมดสามารถรับเหตุการณ์ตัวชี้ได้ แต่พื้นที่นอกวงกลมไม่สามารถทำได้

ดู Pen Visible เทียบกับทาสีใน SVG โดย Tiffany Brown (@webinista) บน CodePen

ดู Pen Visible เทียบกับทาสีใน SVG โดย Tiffany Brown (@webinista) บน CodePen

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

มาทำการเปลี่ยนแปลงเล็กน้อยกับมาร์กอัปของเรา เราจะเพิ่ม pointer-events="visible" ให้กับองค์ประกอบ circle ของเรา ในขณะที่ยังคง fill=none

ดูปากกาว่าการเพิ่มเหตุการณ์ตัวชี้: ทั้งหมดส่งผลต่อการโต้ตอบโดย Tiffany Brown (@webinista) บน CodePen

ดูปากกาว่าการเพิ่มเหตุการณ์ตัวชี้: ทั้งหมดส่งผลต่อการโต้ตอบโดย Tiffany Brown (@webinista) บน CodePen

ตอนนี้พื้นที่ที่ไม่ได้ทาสีที่ล้อมรอบด้วยจังหวะสามารถรับเหตุการณ์ตัวชี้ได้

การเพิ่มพื้นที่ที่สามารถคลิกได้ของรูปภาพ SVG

กลับไปที่ภาพตั้งแต่ต้นบทความนี้ “อเมทิสต์” ของเราเป็นองค์ประกอบของ path ซึ่งต่างจากกลุ่มของรูปหลายเหลี่ยมที่แต่ละอันมี stroke และ fill นั่นหมายความว่าเราไม่สามารถเพิ่ม pointer-events="all" และเรียกวันนี้ว่าวันได้

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

ดู Pen Augmenting พื้นที่การคลิกของภาพ SVG โดย Tiffany Brown (@webinista) บน CodePen

ดู Pen Augmenting พื้นที่การคลิกของภาพ SVG โดย Tiffany Brown (@webinista) บน CodePen

แม้ว่าสี่เหลี่ยมผืนผ้านี้จะมองไม่เห็น แต่ก็ยังมองเห็นได้ใน ทางเทคนิค (เช่น visibility: visible ) อย่างไรก็ตาม หากไม่มีการเติม หมายความว่าไม่ได้ ทาสี ภาพลักษณ์ของเราก็เหมือนกัน แท้จริงแล้วมันยังคงทำงานเหมือนเดิม การคลิกพื้นที่สีขาวยังคงไม่ทริกเกอร์การดำเนินการนำทาง เรายังต้องเพิ่มแอตทริบิวต์ pointer-events ให้ a องค์ประกอบของเรา การใช้ค่าที่ visible หรือ all จะทำงานที่นี่

ดู Pen Augmenting พื้นที่การคลิกของภาพ SVG โดย Tiffany Brown (@webinista) บน CodePen

ดู Pen Augmenting พื้นที่การคลิกของภาพ SVG โดย Tiffany Brown (@webinista) บน CodePen

ตอนนี้รูปภาพทั้งหมดสามารถรับเหตุการณ์ตัวชี้ได้

การใช้ bounding-box จะทำให้ไม่จำเป็นต้องใช้องค์ประกอบ phantom ทุกจุดในกล่องขอบเขตจะได้รับเหตุการณ์ตัวชี้ รวมถึงพื้นที่สีขาวที่ล้อมรอบด้วยเส้นทาง แต่อีกครั้ง: pointer-events="bounding-box" ไม่รองรับอย่างกว้างขวาง จนกว่าจะเป็นอย่างนั้น เราสามารถใช้องค์ประกอบที่ไม่ทาสีได้

การใช้ pointer-events เมื่อผสม SVG และ HTML

อีกกรณีหนึ่งที่ pointer-events อาจเป็นประโยชน์: การใช้ SVG ภายในปุ่ม HTML

ดู Pen Ovxmmy โดย Tiffany Brown (@webinista) บน CodePen

ดู Pen Ovxmmy โดย Tiffany Brown (@webinista) บน CodePen

ในเบราว์เซอร์ส่วนใหญ่ — Firefox และ Internet Explorer 11 เป็นข้อยกเว้น — ค่าของ event.target จะเป็นองค์ประกอบ SVG แทนที่จะเป็นปุ่ม HTML ของเรา มาเพิ่ม pointer-events="none" ให้กับแท็ก SVG เปิดของเรา

See the Pen How pointer-events: none can be used with SVG and HTML by Tiffany Brown (@webinista) บน CodePen.

See the Pen How pointer-events: none can be used with SVG and HTML by Tiffany Brown (@webinista) บน CodePen.

ตอนนี้เมื่อผู้ใช้คลิกหรือแตะปุ่มของเรา event.target จะอ้างอิงถึง button ของเรา

ผู้ที่มีความรอบรู้ใน DOM และ JavaScript จะสังเกตว่าการใช้คีย์เวิร์ดของ function แทนฟังก์ชันลูกศร และใช้คีย์เวิร์ด this แทน event.target เพื่อแก้ไขปัญหานี้ อย่างไรก็ตาม การใช้ pointer-events="none" (หรือ pointer-events: none; ใน CSS ของคุณ) หมายความว่าคุณไม่จำเป็นต้องคอมมิต JavaScript เฉพาะกับหน่วยความจำ

บทสรุป

SVG รองรับการโต้ตอบแบบเดียวกับที่เราคุ้นเคยกับ HTML เราสามารถใช้เพื่อสร้างแผนภูมิที่ตอบสนองต่อการคลิกหรือการแตะ เราสามารถสร้างพื้นที่เชื่อมโยงที่ไม่เป็นไปตามรูปแบบกล่อง CSS และ HTML และด้วยการเพิ่ม pointer-events เราสามารถปรับปรุงวิธีการทำงานของเอกสาร SVG ของเราเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้

การรองรับเบราว์เซอร์สำหรับ pointer-events SVG นั้นแข็งแกร่ง ทุกเบราว์เซอร์ที่รองรับ SVG จะรองรับคุณสมบัติสำหรับเอกสารและองค์ประกอบ SVG เมื่อใช้กับองค์ประกอบ HTML การสนับสนุนจะแข็งแกร่งน้อยกว่าเล็กน้อย ไม่มีใน Internet Explorer 10 หรือรุ่นก่อน หรือ Opera Mini เวอร์ชันใดๆ

เราเพิ่งขีดข่วนพื้นผิวของ pointer-events ในชิ้นนี้ สำหรับการรักษาทางเทคนิคในเชิงลึกยิ่งขึ้น โปรดอ่านข้อกำหนด SVG MDN (Mozilla Developer Network) Web Docs มีเอกสารประกอบที่เป็นมิตรกับนักพัฒนาเว็บเพิ่มเติมสำหรับ pointer-events พร้อมตัวอย่าง