การจัดการการโต้ตอบ SVG ด้วยคุณสมบัติเหตุการณ์ตัวชี้
เผยแพร่แล้ว: 2022-03-10pointer-events
ลองคลิกหรือแตะรูปภาพ SVG ด้านล่าง หากคุณวางตัวชี้ในตำแหน่งที่ถูกต้อง (เส้นทางที่แรเงา) คุณควรเปิดหน้าแรกของ Smashing Magazine ในแท็บเบราว์เซอร์ใหม่ หากคุณพยายามคลิกบนพื้นที่สีขาว คุณอาจจะสับสนแทน
นี่คือภาวะที่กลืนไม่เข้าคายไม่ออกที่ฉันเผชิญระหว่างโปรเจ็กต์ล่าสุดที่รวมลิงก์ไว้ในอิมเมจ 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
ซึ่งหมายความว่าเฉพาะส่วนที่ทาสีและมองเห็นได้เท่านั้นที่จะได้รับเหตุการณ์ตัวชี้ ค่าอื่นๆ ส่วนใหญ่สามารถแบ่งออกเป็นสองกลุ่ม:
- ค่าที่ต้องการองค์ประกอบเพื่อให้มองเห็นได้ และ
- ค่าที่ไม่.
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
แสดงให้เห็นได้ดีกว่าที่อธิบาย เรามาดูตัวอย่างกัน
ที่นี่เรามีวงกลมที่มีการเติมและเส้นขีด มีทั้ง ทาสี และ มองเห็นได้ วงกลมทั้งหมดสามารถรับเหตุการณ์ตัวชี้ได้ แต่พื้นที่นอกวงกลมไม่สามารถทำได้
ปิดใช้งานการเติมเพื่อให้ค่าเป็น none
ตอนนี้ หากคุณพยายามวางเมาส์เหนือ คลิกหรือแตะภายในวงกลม จะไม่มีอะไรเกิดขึ้น แต่ถ้าคุณทำเช่นเดียวกันกับพื้นที่โรคหลอดเลือดสมอง เหตุการณ์ตัวชี้จะยังคงถูกส่งไป การเปลี่ยนค่า fill
เป็น none
หมายความว่าพื้นที่นี้ มองเห็นได้ แต่ไม่ได้ ทาสี
มาทำการเปลี่ยนแปลงเล็กน้อยกับมาร์กอัปของเรา เราจะเพิ่ม pointer-events="visible"
ให้กับองค์ประกอบ circle
ของเรา ในขณะที่ยังคง fill=none
ตอนนี้พื้นที่ที่ไม่ได้ทาสีที่ล้อมรอบด้วยจังหวะสามารถรับเหตุการณ์ตัวชี้ได้
การเพิ่มพื้นที่ที่สามารถคลิกได้ของรูปภาพ SVG
กลับไปที่ภาพตั้งแต่ต้นบทความนี้ “อเมทิสต์” ของเราเป็นองค์ประกอบของ path
ซึ่งต่างจากกลุ่มของรูปหลายเหลี่ยมที่แต่ละอันมี stroke
และ fill
นั่นหมายความว่าเราไม่สามารถเพิ่ม pointer-events="all"
และเรียกวันนี้ว่าวันได้
แต่เราจำเป็นต้องเพิ่มพื้นที่การคลิกแทน ลองใช้สิ่งที่เรารู้เกี่ยวกับองค์ประกอบที่ทาสีและมองเห็นได้ ในตัวอย่างด้านล่าง ฉันได้เพิ่มสี่เหลี่ยมลงในมาร์กอัปรูปภาพของเรา
แม้ว่าสี่เหลี่ยมผืนผ้านี้จะมองไม่เห็น แต่ก็ยังมองเห็นได้ใน ทางเทคนิค (เช่น visibility: visible
) อย่างไรก็ตาม หากไม่มีการเติม หมายความว่าไม่ได้ ทาสี ภาพลักษณ์ของเราก็เหมือนกัน แท้จริงแล้วมันยังคงทำงานเหมือนเดิม การคลิกพื้นที่สีขาวยังคงไม่ทริกเกอร์การดำเนินการนำทาง เรายังต้องเพิ่มแอตทริบิวต์ pointer-events
ให้ a
องค์ประกอบของเรา การใช้ค่าที่ visible
หรือ all
จะทำงานที่นี่
ตอนนี้รูปภาพทั้งหมดสามารถรับเหตุการณ์ตัวชี้ได้
การใช้ bounding-box
จะทำให้ไม่จำเป็นต้องใช้องค์ประกอบ phantom ทุกจุดในกล่องขอบเขตจะได้รับเหตุการณ์ตัวชี้ รวมถึงพื้นที่สีขาวที่ล้อมรอบด้วยเส้นทาง แต่อีกครั้ง: pointer-events="bounding-box"
ไม่รองรับอย่างกว้างขวาง จนกว่าจะเป็นอย่างนั้น เราสามารถใช้องค์ประกอบที่ไม่ทาสีได้
การใช้ pointer-events
เมื่อผสม SVG และ HTML
อีกกรณีหนึ่งที่ pointer-events
อาจเป็นประโยชน์: การใช้ SVG ภายในปุ่ม HTML
ในเบราว์เซอร์ส่วนใหญ่ — Firefox และ Internet Explorer 11 เป็นข้อยกเว้น — ค่าของ event.target
จะเป็นองค์ประกอบ SVG แทนที่จะเป็นปุ่ม HTML ของเรา มาเพิ่ม pointer-events="none"
ให้กับแท็ก SVG เปิดของเรา
ตอนนี้เมื่อผู้ใช้คลิกหรือแตะปุ่มของเรา 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
พร้อมตัวอย่าง