วิธีเข้าถึงแอนิเมชั่น SVG ใน CSS
เผยแพร่แล้ว: 2022-03-11แอนิเมชั่นเป็นส่วนหนึ่งของเว็บที่แพร่หลาย แอนิเมชั่นของวันนี้ต่างจากภาพ GIF ที่กระพริบไปมาซึ่งรบกวนเว็บไซต์ในยุคก่อนๆ นักออกแบบและผู้เชี่ยวชาญส่วนหน้าใช้เพื่อทำให้เว็บไซต์ดูสวยงามยิ่งขึ้น ปรับปรุงประสบการณ์ผู้ใช้ เรียกความสนใจไปยังองค์ประกอบที่สำคัญ และถ่ายทอดข้อมูล
นักพัฒนาเว็บจะได้ประโยชน์จากการผสมผสานพลังของ SVG และ CSS เพื่อสร้างแอนิเมชั่นโดยไม่ต้องใช้ไลบรารี่ภายนอก บทแนะนำแอนิเมชั่น SVG นี้แสดงวิธีสร้างแอนิเมชั่นแบบกำหนดเองสำหรับโปรเจ็กต์ในโลกแห่งความเป็นจริง
แอนิเมชั่น SVG โดยใช้ CSS: แนวคิดหลัก
ก่อนที่จะสร้างภาพเคลื่อนไหว SVG ด้วย CSS นักพัฒนาจำเป็นต้องเข้าใจว่า SVG ทำงานอย่างไรภายใน โชคดีที่มันคล้ายกับ HTML: เรากำหนดองค์ประกอบ SVG ด้วยไวยากรณ์ XML และจัดรูปแบบด้วย CSS เหมือนกับว่าเป็น HTML
องค์ประกอบ SVG ถูกสร้างขึ้นมาเพื่อการวาดกราฟิกโดยเฉพาะ เราสามารถใช้ <rect> ในการวาดรูปสี่เหลี่ยมผืนผ้า <circle> สำหรับการวาดวงกลม ฯลฯ—SVG ยังกำหนด <ellipse> , <line> , <polyline> , <polygon> และ <path>
หมายเหตุ: รายการองค์ประกอบ SVG ทั้งหมด ยังมี <animate> ซึ่งช่วยให้คุณสร้างภาพเคลื่อนไหวโดยใช้ภาษาการรวมมัลติมีเดียที่ซิงโครไนซ์ (SMIL) อย่างไรก็ตาม อนาคตของมันไม่แน่นอน และทีม Chromium แนะนำให้ใช้วิธีการแบบ CSS หรือ JavaScript ในการสร้างภาพเคลื่อนไหว SVG ทุกครั้งที่ทำได้
คุณลักษณะที่ใช้ได้ขึ้นอยู่กับองค์ประกอบ ดังนั้นในขณะที่ <rect> มีแอตทริบิวต์ width และ height องค์ประกอบ <circle> มีแอตทริบิวต์ r ซึ่งกำหนดรัศมี
แม้ว่าองค์ประกอบ HTML ส่วนใหญ่จะมีลูกได้ แต่องค์ประกอบ SVG ส่วนใหญ่ก็ไม่สามารถทำได้ ข้อยกเว้นประการหนึ่งคือองค์ประกอบกลุ่ม <g> ซึ่งเราสามารถใช้เพื่อนำรูปแบบ CSS และการแปลงไปใช้กับองค์ประกอบหลายรายการพร้อมกัน
<svg> องค์ประกอบและคุณสมบัติของมัน
ความแตกต่างที่สำคัญอีกประการระหว่าง HTML และ SVG คือวิธีที่เราวางตำแหน่งองค์ประกอบ โดยเฉพาะอย่างยิ่งผ่านแอตทริบิวต์ viewBox ขององค์ประกอบ <svg> ภายนอกที่กำหนด ค่าประกอบด้วยตัวเลขสี่ตัวที่คั่นด้วยช่องว่างหรือเครื่องหมายจุลภาค: min-x , min-y , width และ height เมื่อรวมกันแล้ว สิ่งเหล่านี้จะระบุจำนวนภาพวาด SVG ของเราที่เราต้องการให้เบราว์เซอร์แสดงผล พื้นที่นั้นจะได้รับการปรับขนาดให้พอดีกับขอบเขตของ วิวพอร์ต ตามที่กำหนดโดยแอตทริบิวต์ width และ height ขององค์ประกอบ <svg>
เมื่อพูดถึงแถบดำ อัตราส่วนของแอตทริบิวต์ width และ height ของวิวพอร์ตอาจแตกต่างจากอัตราส่วนของส่วน width และ height ของแอตทริบิวต์ viewBox อย่างแท้จริง
ตามค่าเริ่มต้น อัตราส่วนกว้างยาวของแคนวาส SVG จะถูกรักษาไว้โดยเสียค่าใช้จ่ายของ viewBox ที่ใหญ่กว่าที่ระบุ ซึ่งจะทำให้การแสดงผลแบบแถบดำที่มีแถบดำเล็กลงภายในวิวพอร์ต แต่คุณสามารถระบุลักษณะการทำงานอื่นได้ผ่านแอตทริบิวต์ preserveAspectRatio
ซึ่งช่วยให้เราสามารถวาดภาพแยกส่วนและมั่นใจได้ว่าองค์ประกอบทั้งหมดจะถูกจัดตำแหน่งอย่างถูกต้องไม่ว่าบริบทหรือขนาดการเรนเดอร์จะเป็นอย่างไร
แม้ว่าคุณจะเขียนโค้ดรูปภาพ SVG ได้ด้วยมือ แต่รูปภาพที่ซับซ้อนกว่าอาจต้องใช้โปรแกรมกราฟิกแบบเวกเตอร์ (บทช่วยสอนเกี่ยวกับแอนิเมชัน SVG ของเราสาธิตเทคนิคทั้งสอง) โปรแกรมแก้ไขที่ฉันเลือกคือ Affinity Designer แต่โปรแกรมแก้ไขใดๆ ควรมีฟังก์ชันเพียงพอสำหรับการดำเนินการอย่างง่ายที่กล่าวถึงในที่นี้
การเปลี่ยน CSS และแอนิเมชั่น
การเปลี่ยน CSS ทำให้เราสามารถกำหนดอัตราและระยะเวลาของการเปลี่ยนแปลงคุณสมบัติได้ แทนที่จะกระโดดจากค่าเริ่มต้นไปยังค่าสิ้นสุดทันที ค่าต่างๆ จะเปลี่ยนไปอย่างราบรื่นดังในตัวอย่างนี้ ซึ่งสีของวงกลม SVG จะเปลี่ยนไปเมื่อคุณวางเมาส์เหนือค่านั้น:
ดูตัวอย่างการเปลี่ยนปากกาโดย Filip Defar (@dabrorius) บน CodePen
เราสามารถกำหนดทรานซิชันด้วยคุณสมบัติ transition ซึ่งยอมรับชื่อของคุณสมบัติที่เราต้องการเปลี่ยน ระยะเวลาของการเปลี่ยนแปลง ฟังก์ชันกำหนดเวลาการเปลี่ยน (หรือเรียกอีกอย่างว่าฟังก์ชันการค่อยๆ เปลี่ยน) และระยะเวลาของการหน่วงเวลาก่อนเริ่มเอฟเฟกต์ :
/* property name | duration | easing function | delay */ transition: margin-right 4s ease-in-out 1s;เราสามารถกำหนดทรานซิชันสำหรับคุณสมบัติ CSS หลายรายการ ซึ่งแต่ละรายการสามารถมีค่าการเปลี่ยนแปลงแยกกันได้ อย่างไรก็ตาม มีข้อจำกัดที่ชัดเจนสองประการสำหรับแนวทางนี้
ข้อจำกัดแรกคือ การเปลี่ยนจะถูกทริกเกอร์โดยอัตโนมัติเมื่อค่าคุณสมบัติเปลี่ยนแปลง ซึ่งไม่สะดวกในบางกรณี ตัวอย่างเช่น เราไม่สามารถมีแอนิเมชั่นที่วนซ้ำไม่รู้จบ
ข้อจำกัดที่สองคือ การเปลี่ยนมักจะมีสองขั้นตอน: สถานะเริ่มต้นและสถานะสุดท้าย เราสามารถขยายระยะเวลาของแอนิเมชั่นได้ แต่เราไม่สามารถเพิ่มคีย์เฟรมที่แตกต่างกันได้
นี่คือสาเหตุที่ทำให้มีแนวคิดที่มีประสิทธิภาพมากขึ้น: ภาพเคลื่อนไหว CSS ด้วยแอนิเมชั่น CSS เราสามารถมีได้หลายคีย์เฟรมและวนซ้ำไม่สิ้นสุด:
ดูตัวอย่างอนิเมชั่นปากกาโดย Filip Defar (@dabrorius) บน CodePen
ในการทำให้คุณสมบัติ CSS เคลื่อนไหวบนหลายคีย์เฟรม ก่อนอื่นเราต้องกำหนดคีย์เฟรมโดยใช้ @keyframes at-rule ระยะเวลาของคีย์เฟรมถูกกำหนดในหน่วยที่เกี่ยวข้อง (เปอร์เซ็นต์) เนื่องจาก ณ จุดนี้ เรายังไม่ได้กำหนดระยะเวลาของภาพเคลื่อนไหว แต่ละคีย์เฟรมอธิบายค่าของคุณสมบัติ CSS อย่างน้อย 1 รายการ ณ เวลานั้น ภาพเคลื่อนไหว CSS จะช่วยให้การเปลี่ยนระหว่างคีย์เฟรมเป็นไปอย่างราบรื่น
เราใช้แอนิเมชั่นพร้อมคีย์เฟรมที่อธิบายกับองค์ประกอบที่ต้องการโดยใช้คุณสมบัติ animation เช่นเดียวกับคุณสมบัติ transition โดยจะยอมรับระยะเวลา ฟังก์ชันการค่อยๆ เปลี่ยน และความล่าช้า
ข้อแตกต่างเพียงอย่างเดียวคือพารามิเตอร์แรกคือชื่อ @keyframes ของเราแทนที่จะเป็นชื่อคุณสมบัติ:
/* @keyframes name | duration | easing-function | delay */ animation: my-sliding-animation 3s linear 1s;การทำแอนิเมชั่นเมนูแฮมเบอร์เกอร์ Toggle
ตอนนี้ เรามีความเข้าใจพื้นฐานเกี่ยวกับวิธีการทำงานของ SVG ที่เป็นแอนิเมชันแล้ว เราสามารถเริ่มสร้างแอนิเมชั่นแบบคลาสสิกได้ ซึ่งเป็นการสลับเมนูที่เปลี่ยนระหว่างไอคอน "แฮมเบอร์เกอร์" และปุ่มปิด ("X") ได้อย่างราบรื่น:
ดู Pen Hamburger โดย Filip Defar (@dabrorius) บน CodePen
นี่เป็นแอนิเมชั่นที่ละเอียดอ่อนแต่มีค่า ดึงดูดความสนใจของผู้ใช้โดยแจ้งว่าสามารถใช้ไอคอนเพื่อปิดเมนูได้
เราเริ่มการสาธิตโดยการสร้างองค์ประกอบ SVG ที่มีสามบรรทัด:
<svg class="hamburger"> <line x1="0" y1="50%" x2="100%" y2="50%" class="hamburger__bar hamburger__bar--top" /> <line x1="0" y1="50%" x2="100%" y2="50%" class="hamburger__bar hamburger__bar--mid" /> <line x1="0" y1="50%" x2="100%" y2="50%" class="hamburger__bar hamburger__bar--bot" /> </svg> แต่ละบรรทัดมีแอตทริบิวต์สองชุด x1 และ y1 แทนพิกัดของจุดเริ่มต้นของเส้น ในขณะที่ x2 และ y2 แสดงถึงพิกัดของจุดสิ้นสุดของเส้น เราใช้หน่วยสัมพัทธ์เพื่อกำหนดตำแหน่ง นี่เป็นวิธีง่ายๆ ในการตรวจสอบให้แน่ใจว่าเนื้อหารูปภาพได้รับการปรับขนาดให้พอดีกับองค์ประกอบ SVG ที่มีอยู่ แม้ว่าวิธีการนี้จะได้ผลในกรณีนี้ แต่ก็มีข้อเสียอย่างหนึ่งคือ เราไม่สามารถรักษาอัตราส่วนกว้างยาวขององค์ประกอบที่วางตำแหน่งในลักษณะนี้ได้ เราจะต้องใช้แอตทริบิวต์ viewBox ขององค์ประกอบ <svg>
โปรดทราบว่าเราใช้คลาส CSS กับองค์ประกอบ SVG มีคุณสมบัติมากมายที่สามารถเปลี่ยนแปลงได้ผ่าน CSS ดังนั้น ลองใช้สไตล์พื้นฐานกับองค์ประกอบ SVG ของเรา
เราจะกำหนดขนาดขององค์ประกอบ <svg> รวมทั้งเปลี่ยนประเภทเคอร์เซอร์เพื่อระบุว่าคลิกได้ แต่ในการกำหนดสีและความหนาของเส้น เราจะใช้คุณสมบัติ stroke และ stroke-width คุณอาจคาดว่าจะใช้ color หรือ border แต่ต่างจาก <svg> องค์ประกอบย่อย SVG ไม่ใช่องค์ประกอบ HTML ดังนั้นจึงมักมีชื่อคุณสมบัติต่างกัน:
.hamburger { width: 62px; height: 62px; cursor: pointer; } .hamburger__bar { stroke: white; stroke-width: 10%; } หากเราเรนเดอร์ ณ จุดนี้ เราจะเห็นว่าทั้งสามบรรทัดมีขนาดและตำแหน่งเท่ากัน โดยซ้อนทับกันอย่างสมบูรณ์ ขออภัย เราไม่สามารถเปลี่ยนตำแหน่งเริ่มต้นและสิ้นสุดได้ อย่างอิสระ ผ่าน CSS แต่เราสามารถย้ายองค์ประกอบทั้งหมดได้ มาย้ายแถบด้านบนและด้านล่างด้วยคุณสมบัติการ transform CSS:
.hamburger__bar--top { transform: translateY(-40%); } .hamburger__bar--bot { transform: translateY(40%); }การขยับแถบบนแกน Y ทำให้ได้แฮมเบอร์เกอร์ที่ดูดี
ตอนนี้ได้เวลาเขียนโค้ดสถานะที่สองของเราแล้ว: ปุ่มปิด เราใช้คลาส CSS .is-opened ใช้กับองค์ประกอบ SVG เพื่อสลับระหว่างสองสถานะ เพื่อให้เข้าถึงผลลัพธ์ได้มากขึ้น ให้รวม SVG ของเราไว้ในองค์ประกอบ <button> และจัดการการคลิกในระดับนั้น
ขั้นตอนการเพิ่มและลบคลาสจะได้รับการจัดการโดยข้อมูลโค้ด JavaScript อย่างง่าย:
const hamburger = document.querySelector("button"); hamburger.addEventListener("click", () => { hamburger.classList.toggle("is-opened"); }); ในการสร้าง X ของเรา เราสามารถใช้คุณสมบัติ transform ที่แตกต่างกันกับแท่งแฮมเบอร์เกอร์ของเราได้ เนื่องจากคุณสมบัติ transform แบบใหม่จะแทนที่คุณสมบัติเก่า จุดเริ่มต้นของเราจะเป็นตำแหน่งเดิมที่ใช้ร่วมกันของแถบสามแท่ง
จากนั้น เราสามารถหมุนแถบด้านบน 45 องศาตามเข็มนาฬิกาไปรอบๆ ศูนย์กลาง และหมุนแถบด้านล่าง 45 องศาทวนเข็มนาฬิกา เราสามารถย่อแถบกลางในแนวนอนจนแคบพอที่จะซ่อนไว้ด้านหลังจุดศูนย์กลางของ X:
.is-opened .hamburger__bar--top { transform: rotate(45deg); } .is-opened .hamburger__bar--mid { transform: scaleX(0.1); } .is-opened .hamburger__bar--bot { transform: rotate(-45deg); } โดยค่าเริ่มต้น คุณสมบัติ transform-origin สำหรับองค์ประกอบ SVG ปกติแล้วจะเป็น 0,0 ซึ่งหมายความว่าแถบของเราจะหมุนไปรอบๆ มุมบนซ้ายของวิวพอร์ต แต่เราต้องการให้แถบเหล่านั้นหมุนไปรอบๆ ตรงกลาง ในการแก้ไขปัญหานี้ ให้ตั้งค่าคุณสมบัติ transform-origin ให้ center สำหรับคลาส . .hamburger__bar

คุณสมบัติ CSS เคลื่อนไหวด้วย transition
คุณสมบัติ transition CSS บอกให้เบราว์เซอร์ทำการเปลี่ยนแปลงระหว่างสองสถานะที่แตกต่างกันของคุณสมบัติ CSS อย่างราบรื่น ในที่นี้ เราต้องการทำให้การเปลี่ยนแปลงของเราในคุณสมบัติการ transform เป็นภาพเคลื่อนไหว ซึ่งกำหนดตำแหน่ง การวางแนว และมาตราส่วนของแท่ง
นอกจากนี้เรายังสามารถควบคุมระยะเวลาของการเปลี่ยนแปลงได้โดยใช้คุณสมบัติ transition-duration เพื่อให้แอนิเมชั่นดูฉับไว เราจะตั้งค่าระยะเวลาสั้นๆ 0.3 วินาที:
.hamburger__bar { transition-property: transform; transition-duration: 0.3s; ... }JavaScript ชิ้นเดียวที่เราต้องการคือบิตที่ทำให้สถานะไอคอนสลับได้:
const hamburger = document.querySelector("button"); hamburger.addEventListener("click", () => { hamburger.classList.toggle("is-opened"); }); ที่นี่ เราเลือกองค์ประกอบ SVG ภายนอกตามคลาส .mute โดยใช้ .mute querySelector() จากนั้นเราจะเพิ่มตัวฟังเหตุการณ์การคลิก เมื่อมีการทริกเกอร์เหตุการณ์การคลิก เราจะสลับคลาส .is-active เฉพาะใน <svg> เท่านั้น โดยไม่อยู่ในลำดับชั้นที่ลึกกว่า เนื่องจากเราสร้างแอนิเมชั่น CSS ให้ใช้กับองค์ประกอบที่มีคลาส .is-active เท่านั้น การสลับคลาสนี้จะเปิดใช้งานและปิดใช้งานแอนิเมชั่น
ในขั้นสุดท้าย เราจะแปลงเนื้อหา HTML เป็นคอนเทนเนอร์แบบยืดหยุ่น ซึ่งจะช่วยให้เราจัดไอคอนให้อยู่กึ่งกลางในแนวนอนและแนวตั้ง นอกจากนี้ เราจะอัปเดตสีพื้นหลังเป็นสีเทาเข้มมากและสีไอคอนเป็นสีขาว เพื่อให้ได้รูปลักษณ์ "โหมดมืด" ที่ทันสมัย:
body { display: flex; justify-content: center; align-items: center; background-color: #222; height: 100vh; }ด้วยเหตุนี้ เราจึงได้สร้างปุ่มภาพเคลื่อนไหวที่ทำงานได้อย่างสมบูรณ์โดยใช้ CSS พื้นฐานและตัวอย่าง JavaScript แบบสั้น ง่ายต่อการเปลี่ยนการแปลงที่เรานำไปใช้เพื่อสร้างแอนิเมชั่นที่หลากหลาย ผู้อ่านสามารถแยก CodePen ซึ่งรวมถึง CSS พิเศษเล็กน้อยสำหรับการขัดเงาและสร้างสรรค์
การทำงานกับข้อมูล SVG จากบรรณาธิการภายนอก
เมนูแฮมเบอร์เกอร์ของเรานั้นง่ายมาก ถ้าเราต้องการทำอะไรที่ซับซ้อนกว่านี้ล่ะ? นั่นคือจุดที่การเข้ารหัส SVG ด้วยมือกลายเป็นเรื่องยากและซอฟต์แวร์แก้ไขกราฟิกแบบเวกเตอร์สามารถช่วยได้
แอนิเมชั่น SVG ที่สองของเราคือปุ่มปิดเสียงที่แสดงไอคอนหูฟัง เมื่อเปิดเพลง ไอคอนจะเต้นเป็นจังหวะ เมื่อปิดเสียง ไอคอนจะถูกขีดฆ่า:
ดูปุ่ม Pen Mute - 5 - ขีดทับสีแดงโดย Filip Defar (@dabrorius) บน CodePen
ไอคอนรูปวาดจะอยู่นอกขอบเขตของบทช่วยสอนนี้ (และอาจเป็นรายละเอียดงานของคุณ) ดังนั้นเราจะเริ่มด้วยไอคอน SVG ที่วาดไว้ล่วงหน้า นอกจากนี้เรายังต้องการการจัดรูปแบบ body เช่นเดียวกับตัวอย่างเมนูแฮมเบอร์เกอร์ของเรา
คุณอาจต้องการล้างรหัส SVG ก่อนใช้งาน คุณสามารถทำได้ด้วย svgo ซึ่งเป็นเครื่องมือเพิ่มประสิทธิภาพ SVG แบบโอเพนซอร์สที่ใช้ Node.js สิ่งนี้จะลบองค์ประกอบที่ไม่จำเป็นออก และทำให้รหัสง่ายต่อการแก้ไขด้วยมือ ซึ่งคุณจะต้องทำเพื่อเพิ่มคลาสและรวมองค์ประกอบต่างๆ
ไอคอน SVG ที่สร้างในซอฟต์แวร์แก้ไขภาพไม่น่าจะใช้หน่วยที่เกี่ยวข้อง นอกจากนี้ เราต้องการตรวจสอบให้แน่ใจว่าอัตราส่วนกว้างยาวของไอคอนยังคงอยู่ โดยไม่คำนึงถึงอัตราส่วนกว้างยาวขององค์ประกอบ SVG ที่มีอยู่ เพื่อให้การควบคุมระดับนี้เป็นไปได้ เราจะใช้แอตทริบิวต์ viewBox
เป็นความคิดที่ดีที่จะปรับขนาด SVG เพื่อให้สามารถตั้งค่า viewBox เป็นค่าที่ใช้งานง่าย ในกรณีนี้ ฉันได้แปลงเป็น viewBox ที่มีขนาด 100 x 100 พิกเซล
ตรวจสอบให้แน่ใจว่าไอคอนอยู่ตรงกลางและมีขนาดเหมาะสม เราจะใช้คลาส mute กับองค์ประกอบ SVG พื้นฐานของเรา แล้วเพิ่มสไตล์ CSS ต่อไปนี้:
.mute { fill: white; width: 80px; height: 70px; cursor: pointer; } ในที่นี้ width จะมากกว่า height เล็กน้อยเพื่อหลีกเลี่ยงการคลิประหว่างการหมุนของแอนิเมชันของเรา
จุดเริ่มต้นแอนิเมชั่น SVG ของเรา
SVG ที่ล้างตอนนี้มีองค์ประกอบ <g> เดียวที่มีองค์ประกอบ <path> สามรายการ
องค์ประกอบเส้นทางช่วยให้เราสามารถวาดเส้น เส้นโค้ง และส่วนโค้งได้ มีการอธิบายเส้นทางด้วยชุดคำสั่งที่อธิบายว่าควรวาดรูปร่างอย่างไร เนื่องจากไอคอนของเราประกอบด้วยรูปร่างที่ไม่เกี่ยวข้องกันสามรูปร่าง เราจึงมีสามเส้นทางที่จะอธิบายรูปร่างเหล่านั้น
องค์ประกอบ g SVG เป็นคอนเทนเนอร์ที่ใช้ในการจัดกลุ่มองค์ประกอบ SVG อื่นๆ เราใช้มันเพื่อปรับใช้การเปลี่ยนแปลงที่เต้นเป็นจังหวะบนทั้งสามเส้นทางพร้อมกัน
<svg class="mute" viewBox="0 0 100 100"> <g> <path d="M92.6,50.075C92.213,26.775 73.25,7.938 50,7.938C26.75,7.938 7.775,26.775 7.388,50.075C3.112,51.363 -0.013,55.425 -0.013,60.25L-0.013,72.7C-0.013,78.55 4.575,83.3 10.238,83.3L18.363,83.3L18.363,51.6C18.4,51.338 18.438,51.075 18.438,50.813C18.438,33.275 32.6,19 50,19C67.4,19 81.563,33.275 81.563,50.813C81.563,51.088 81.6,51.338 81.638,51.6L81.638,83.313L89.763,83.313C95.413,83.313 100.013,78.563 100.013,72.713L100.013,60.263C100,55.438 96.875,51.362 92.6,50.075Z" /> <path d="M70.538,54.088L70.538,79.588C70.538,81.625 72.188,83.275 74.225,83.275L74.225,83.325L78.662,83.325L78.662,50.4L74.225,50.4C72.213,50.4 70.538,52.063 70.538,54.088Z" /> <path d="M25.75,50.4L21.313,50.4L21.313,83.325L25.75,83.325L25.75,83.275C27.788,83.275 29.438,81.625 29.438,79.588L29.438,54.088C29.45,52.063 27.775,50.4 25.75,50.4Z" /> </g> </svg> เพื่อให้หูฟังเต้นเป็นจังหวะ ท transition สิชั่นไม่เพียงพอ นี่เป็นตัวอย่างที่ซับซ้อนพอที่จะต้องใช้คีย์เฟรม
ในกรณีนี้ คีย์เฟรมเริ่มต้นและสิ้นสุดของเรา (ที่ 0% และ 100% ของแอนิเมชัน ตามลำดับ) จะใช้ไอคอนหูฟังที่ย่อให้เล็กลงเล็กน้อย สำหรับ 40% แรกของแอนิเมชั่น เราจะขยายรูปภาพเล็กน้อยและเอียง 5 องศา จากนั้น สำหรับ 40% ของแอนิเมชั่นถัดไป เราจะลดขนาดกลับเป็น 0.9x แล้วหมุน 5 องศาไปอีกด้านหนึ่ง สุดท้าย สำหรับ 20% สุดท้ายของแอนิเมชั่น การแปลงไอคอนจะกลับไปเป็นพารามิเตอร์เริ่มต้นเดียวกันเพื่อให้วนซ้ำได้อย่างราบรื่น
@keyframes pulse { 0% { transform: scale(0.9); } 40% { transform: scale(1) rotate(5deg); } 80% { transform: scale(1) rotate(-5deg); } 100% { transform: scale(0.9) rotate(0); } }CSS Animation Optimizations
ในการแสดงวิธีการทำงานของคีย์เฟรม เราปล่อยให้ CSS ของคีย์เฟรมมีความละเอียดมากกว่าที่ควรจะเป็น มีสามวิธีที่เราสามารถย่อให้สั้นลงได้
เนื่องจากคีย์เฟรม 100% ของเราตั้งค่ารายการ transform ทั้งหมด หากเราละเว้นการ rotate() ทั้งหมด ค่าของคีย์เฟรมนั้นจะมีค่าเริ่มต้นเป็น 0:
100% { transform: scale(0.9); } ประการที่สอง เรารู้ว่าเราต้องการให้คีย์เฟรม 0% และ 100% ตรงกัน เนื่องจากเรากำลังวนลูปภาพเคลื่อนไหว ด้วยการกำหนดกฎ CSS เดียวกัน เราจะไม่ต้องจำต้องแก้ไขทั้งสองอย่าง หากเราต้องการเปลี่ยนจุดที่ใช้ร่วมกันนี้ในแอนิเมชั่นลูป:
0%, 100% { transform: scale(0.9); } สุดท้ายนี้ เราจะนำ transform: scale(0.9); ไปที่คลาส mute__headphones และเมื่อเรากำหนด เราไม่จำเป็นต้องกำหนดคีย์เฟรมเริ่มต้นและสิ้นสุดเลย! พวกเขาจะตั้งค่าเริ่มต้นเป็นสไตล์คงที่ที่ใช้โดย mute__headphones
ตอนนี้เราได้กำหนดคีย์เฟรมของแอนิเมชั่นแล้ว เราก็สามารถใช้แอนิเมชั่นได้ เราเพิ่มคลาส .mute__headphones ให้กับองค์ประกอบ <g> เพื่อให้มีผลกับไอคอนหูฟังทั้งสามส่วน ขั้นแรก เราตั้งค่า transform-origin ให้ center อีกครั้ง เนื่องจากเราต้องการให้ไอคอนหมุนไปรอบๆ ศูนย์กลาง นอกจากนี้เรายังปรับขนาดเพื่อให้ขนาดตรงกับคีย์เฟรมของภาพเคลื่อนไหวเริ่มต้น หากไม่มีขั้นตอนนี้ การเปลี่ยนจากไอคอน "ปิดเสียง" แบบคงที่ไปเป็นไอคอนแบบเคลื่อนไหวจะส่งผลให้ขนาดเพิ่มขึ้นอย่างกะทันหันเสมอ (ไม่ว่าจะด้วยวิธีใด การเปลี่ยนกลับไปเป็นแบบปิดเสียงจะทำให้มาตราส่วนเพิ่มขึ้น และมีแนวโน้มว่าจะหมุนด้วย หากผู้ใช้คลิกในขณะที่มาตราส่วนมีขนาดใหญ่กว่า 0.9 เท่า เราไม่สามารถทำอะไรได้มากเกี่ยวกับผลกระทบนั้นด้วย CSS เพียงอย่างเดียว)
เราใช้แอนิเมชั่นโดยใช้คุณสมบัติ CSS ของ animation แต่เฉพาะเมื่อมีคลาสพาเร .is-active เท่านั้น ซึ่งคล้ายกับวิธีที่เราทำให้เมนูแฮมเบอร์เกอร์ของเราเคลื่อนไหว
.mute__headphones { transform-origin: center; transform: scale(0.9); } .is-active .mute__headphones { animation: pulse 2s infinite; }JavaScript ที่เราต้องให้เราสลับไปมาระหว่างสถานะเป็นไปตามรูปแบบเดียวกับเมนูแฮมเบอร์เกอร์ด้วย:
const muteButton = document.querySelector(".mute"); muteButton.addEventListener("click", () => { muteButton.classList.toggle("is-active"); }); ชิ้นต่อไปที่เราจะเพิ่มคือเส้นขีดทับที่ปรากฏขึ้นเมื่อไอคอนไม่ทำงาน เนื่องจากเป็นองค์ประกอบการออกแบบที่เรียบง่าย เราจึงสามารถเขียนโค้ดด้วยตนเองได้ นี่คือจุดที่การมีค่า viewBox ที่เรียบง่ายและสมเหตุสมผลมีประโยชน์ เรารู้ว่าขอบผ้าใบอยู่ที่ 0 และ 100 ดังนั้นจึงง่ายต่อการคำนวณตำแหน่งเริ่มต้นและสิ้นสุดสำหรับเส้นของเรา:
<line x1="12" y1="12" x2="88" y2="88" class="mute__strikethrough" />การปรับขนาดเทียบกับการใช้หน่วยสัมพัทธ์
คุณสามารถสร้างเคสเพื่อใช้หน่วยที่สัมพันธ์กันแทนการปรับขนาดรูปภาพได้ สิ่งนี้ใช้ได้กับตัวอย่างของเรา เนื่องจากเรากำลังเพิ่มเฉพาะบรรทัด SVG ธรรมดาบนไอคอนของเรา
ในสถานการณ์จริง คุณอาจต้องการรวมเนื้อหา SVG ที่ซับซ้อนมากขึ้นจากแหล่งต่างๆ นี่คือสาเหตุที่ทำให้ขนาดเท่ากันทั้งหมดมีประโยชน์ เนื่องจากเราไม่สามารถฮาร์ดโค้ดค่าสัมพัทธ์ด้วยตนเองเหมือนที่เราทำในตัวอย่างของเรา
เนื่องจากเราใช้คลาสกับองค์ประกอบ <line> ขีดทับโดยตรง เราจึงจัดรูปแบบผ่าน CSS ได้ เราแค่ต้องตรวจสอบให้แน่ใจว่ามองไม่เห็นบรรทัดเมื่อไอคอนทำงาน:
.mute__strikethrough { stroke: red; opacity: 0.8; stroke-width: 12px; } .is-active .mute__strikethrough { opacity: 0; } เราสามารถเพิ่มคลาส .is-active ลงใน SVG ได้โดยตรง การทำเช่นนี้จะทำให้แอนิเมชั่นเริ่มทำงานทันทีที่หน้าโหลด ดังนั้นเราจึงเปลี่ยนสถานะเริ่มต้นของไอคอนจากไม่เคลื่อนไหว (ปิดเสียง) เป็นเคลื่อนไหว (ไม่ปิดเสียง)
แอนิเมชั่น SVG แบบ CSS อยู่ที่นี่แล้ว
เราเพิ่งขีดข่วนพื้นผิวของเทคนิคแอนิเมชั่น CSS และวิธีการทำงานของวิวพอร์ต คุณควรทราบวิธีเขียนโค้ด SVG ด้วยมือเพื่อให้แอนิเมชั่นง่ายๆ เรียบง่าย แต่สิ่งสำคัญคือต้องรู้ว่าจะใช้งานกราฟิกที่สร้างด้วยโปรแกรมแก้ไขภายนอกได้อย่างไรและเมื่อใด แม้ว่าเบราว์เซอร์สมัยใหม่จะช่วยให้เราสร้างแอนิเมชั่นที่น่าประทับใจได้โดยใช้ฟังก์ชันในตัวเท่านั้น สำหรับกรณีการใช้งานที่ซับซ้อน (มาก) นักพัฒนาอาจต้องการสำรวจไลบรารีแอนิเมชัน เช่น GSAP หรือ anime.js
ภาพเคลื่อนไหวไม่จำเป็นต้องสงวนไว้สำหรับโครงการฟุ่มเฟือย เทคนิคแอนิเมชั่น CSS สมัยใหม่ช่วยให้เราสร้างแอนิเมชั่นที่น่าดึงดูดและสวยงามมากมายด้วยวิธีที่เรียบง่ายและเข้ากันได้กับเบราว์เซอร์
ขอขอบคุณเป็นพิเศษกับ Mike Zeballos สำหรับการตรวจสอบทางเทคนิคของบทความนี้!
