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

พาธการเคลื่อนไหว SVG: ย้ายไอคอนที่ออกแบบเองไปตามเส้นโค้ง

ย้ายงาน SVG ไปตามเส้นโค้งด้วย animateMotion และ mpath แก้ไอคอนที่เยื้องศูนย์ เลือกการหมุนอัตโนมัติ และเตรียมภาพนิ่งสำหรับผู้ที่ต้องการลดการเคลื่อนไหว

ในหน้านี้

ใช้ animateMotion เพื่อย้ายองค์ประกอบ SVG ไปตามเส้นทาง และใส่ mpath ไว้ภายในเพื่ออ้างอิงพาธที่มีอยู่ rotate="auto" หมุนงานภาพที่เคลื่อนไหวให้หันตามทิศทางของเส้นทาง จุดกำเนิดพิกัดเฉพาะของงานภาพคือจุดที่เดินทางไปตามพาธ ดังนั้นไอคอนที่นำเข้าจึงต้องกำหนดจุดยึดอย่างตั้งใจ

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

แยกเส้นทางออกจากงานภาพ

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

ตัวอย่างที่เราสร้างด้านล่างมีลูกศรสีเขียวอมฟ้าและจุดสีทอง ลูกศรชี้ไปทางแกน X บวก ซึ่งช่วยให้ตรวจผลของการหมุนอัตโนมัติได้ง่าย งานภาพวาดอยู่รอบ (0, 0) แทนที่จะอยู่ห่างออกไปบนผืนภาพส่งออกขนาดใหญ่

บันทึกเป็น motion.html แล้วเปิดในเบราว์เซอร์ ตราสัญลักษณ์แบบนิ่งจะปรากฏก่อน กด Play เพื่อเล่นหนึ่งรอบนานสี่วินาที ส่วน Show static จะคืนภาพประกอบไปยังจุดเริ่มต้น

<!doctype html>
<meta charset="utf-8">
<title>Arrow following a curve</title>
<style>
  svg { display: block; width: min(100%, 800px); }
  .moving { display: none; }
  .playing .moving { display: inline; }
  .playing .still { display: none; }
</style>
 
<svg id="scene" viewBox="0 0 480 240"
     xmlns="http://www.w3.org/2000/svg"
     role="img" aria-label="An arrow emblem follows a curved route">
  <defs>
    <path id="route" d="M60 180 C160 20 300 20 420 180" />
    <g id="emblem">
      <path fill="#147d78"
            d="M-18-12 H4 V-22 L30 0 L4 22 V12 H-18 Z" />
      <circle cx="-7" cy="0" r="4" fill="#e5a340" />
    </g>
  </defs>
 
  <use href="#route" fill="none" stroke="#a9bab6" stroke-width="2" />
  <use class="still" href="#emblem" transform="translate(60 180)" />
  <g class="moving">
    <use href="#emblem" />
    <animateMotion id="motion" dur="4s" begin="indefinite"
                   fill="freeze" rotate="auto">
      <mpath href="#route" />
    </animateMotion>
  </g>
</svg>
 
<button id="play" type="button">Play</button>
<button id="stop" type="button">Show static</button>
<script>
  const scene = document.querySelector("#scene");
  const motion = document.querySelector("#motion");
  const preference = matchMedia("(prefers-reduced-motion: reduce)");
 
  function showStatic() {
    scene.pauseAnimations();
    scene.classList.remove("playing");
  }
 
  document.querySelector("#play").addEventListener("click", () => {
    if (preference.matches) return;
    scene.pauseAnimations();
    scene.setCurrentTime(0);
    scene.classList.add("playing");
    motion.beginElement();
    scene.unpauseAnimations();
  });
  document.querySelector("#stop").addEventListener("click", showStatic);
  preference.addEventListener("change", showStatic);
  showStatic();
</script>

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

fill="freeze" คงสถานะสุดท้ายของแอนิเมชันไว้ ไม่เกี่ยวกับสีเขียวอมฟ้าที่ระบายบนลูกศร ตัวอย่างนี้เล่นเพียงครั้งเดียว จึงตรวจตำแหน่งสุดท้ายได้ง่ายกว่าการเล่นวนไม่สิ้นสุด

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

แก้ไอคอนที่ลอยห่างจากเส้นทาง

การเคลื่อนไหวใช้กับระบบพิกัดขององค์ประกอบ ไม่ได้ค้นหาศูนย์กลางที่มองเห็นของโลโก้ให้อัตโนมัติ หากพาธที่นำเข้าของคุณอยู่รอบพิกัด (200, 120) การย้ายกลุ่มที่ครอบมันไปตามเส้นทางจะยังเก็บระยะเยื้องนั้นไว้ภายในกลุ่ม

เลือกจุดบนงานภาพที่ต้องการให้สัมผัสเส้นทาง แล้วเลื่อนจุดนั้นไปที่ (0, 0) ภายในกลุ่มที่เคลื่อนไหว สำหรับจุดยึดที่ (200, 120) โครงสร้างคือ:

<g class="moving">
  <g transform="translate(-200 -120)">
    <!-- Place the original artwork paths here. -->
  </g>
  <animateMotion dur="4s" rotate="auto">
    <mpath href="#route" />
  </animateMotion>
</g>

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

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

การหมุนอยู่กับที่มีปัญหาเรื่องจุดหมุนของตัวเอง คู่มือ transform-origin ของ SVG อธิบายกรณีนั้นโดยไม่เพิ่มเส้นทางการเดินทาง

เลือกว่าจะให้งานภาพหมุนหรือไม่

ผลลัพธ์ที่ต้องการการตั้งค่าการเคลื่อนไหวการเตรียมงานภาพ
ลูกศรหันตามทิศทางเส้นโค้งrotate="auto"ให้ทิศด้านหน้าชี้ไปทางแกน X บวก
ตราสัญลักษณ์ตั้งตรงระหว่างเคลื่อนที่rotate="0"กำหนดทิศทางคงที่ที่ต้องการไว้ในงานภาพเฉพาะของมัน
งานภาพหันตรงข้ามทิศทางเส้นทางrotate="auto-reverse"ตรวจทิศด้านหน้าของต้นฉบับก่อนใช้

ค่าเหล่านี้มีเอกสารใน เอกสารอ้างอิงการหมุนขณะเคลื่อนไหวของ MDN auto-reverse เปลี่ยนด้านที่หัน แต่ไม่ได้ย้อนลำดับการเดินทางตามเส้นทาง

หากต้นฉบับของคุณชี้ขึ้นด้านบน auto ไม่รู้ว่าด้านบนหมายถึงด้านหน้า ให้หมุนกลุ่มงานภาพด้านในจนชี้ไปทางแกน X บวก แล้วใช้การเคลื่อนไหวกับกลุ่มด้านนอก อย่าหมุนเส้นทางเพียงเพื่อแก้ทิศทางเฉพาะของไอคอน

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

ตรวจจุดเริ่มต้น กลางทาง และจุดสิ้นสุด

เราเปิดเส้นทางและตราสัญลักษณ์เดียวกันใน Chrome และใช้ชุดทดสอบขนาดเล็กเพื่อหยุดไทม์ไลน์ SVG ที่ 0, 2 และ 4 วินาที ไอคอนเริ่มที่ด้านล่างซ้าย ผ่านใกล้ยอดโค้ง และสิ้นสุดที่ด้านล่างขวา เมื่อใช้ auto ด้านที่หันจะเปลี่ยนไปตามเส้นโค้ง เมื่อกำหนดการหมุนเป็น 0 ตำแหน่งกลางทางไม่เปลี่ยน แต่ลูกศรยังคงอยู่ในแนวนอน

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

สำหรับงานภาพของคุณเอง:

  1. ตรวจจุดสัมผัสที่จุดเริ่มต้นของเส้นทาง แก้ระยะเยื้องในต้นฉบับก่อนปรับเวลา
  2. หยุดใกล้ส่วนโค้งและยืนยันว่าส่วนที่ตั้งใจไว้ของตราสัญลักษณ์เคลื่อนตามเส้น
  3. เปรียบเทียบการหมุนอัตโนมัติกับการหมุนคงที่ เลือกตามงานภาพ โดยเฉพาะเมื่อมีข้อความอยู่ด้วย
  4. ตรวจตำแหน่งสุดท้ายว่าถูกตัดหรือไม่ และยืนยันว่าการเล่นซ้ำเริ่มต้นถูกต้อง
  5. ทดสอบบริบทส่งมอบจริง ตัวอย่างนี้ใช้ SVG แบบอินไลน์ภายในหน้า HTML พร้อมตัวควบคุม JavaScript

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

เตรียมภาพนิ่งที่ใช้งานได้

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

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

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

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

เตรียมลวดลายของคุณก่อนทำแอนิเมชัน

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

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

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

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

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

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

ลบเส้นนำทางที่มองเห็นได้หรือไม่? ได้ เก็บคำจำกัดความเส้นทางและ ID ของมันไว้ แต่ลบองค์ประกอบแยกที่วาดเส้นนำทางออก การเคลื่อนไหวยังอ้างอิงพาธผ่าน mpath ได้

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

  1. MDN animateMotion — อธิบายพาธการเคลื่อนไหว ค่าการหมุน และการเคลื่อนไหวตามระยะทางอย่างสม่ำเสมอที่เป็นค่าปริยาย
  2. MDN mpath — อธิบายการอ้างอิงเส้นทางที่มีอยู่ภายในองค์ประกอบการเคลื่อนไหว
  3. ข้อกำหนดแอนิเมชัน SVG — นิยามการแปลงจากการเคลื่อนไหวและความสัมพันธ์กับพิกัดงานภาพ
  4. MDN แอตทริบิวต์ rotate — อธิบายทิศทางขณะเคลื่อนไหวแบบคงที่ อัตโนมัติ และหันกลับด้าน
  5. MDN ความต้องการลดการเคลื่อนไหว — อธิบายการตรวจความต้องการด้านการเคลื่อนไหวของผู้ใช้

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

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