Panduan Animasi SVG (SMIL). Panduan Animasi SVG (SMIL) Animasi Sederhana dalam Contoh svg




Dari penulis: bagaimana jika saya beritahu Anda bahwa ada format gambar yang berfungsi seperti GIF, tetapi hanya dengan grafik vektor? Bagaimana jika saya memberi tahu Anda bahwa dalam format ini Anda dapat mengubah arah animasinya? Jika demikian, dapatkah Anda mengambil satu gambar sebagai dasar dan menganimasikan bagian-bagian berbeda secara terpisah dan dengan kecepatan berbeda? Ya, format seperti itu sudah ada dan itu adalah SVG. Anda hanya perlu sedikit berani.

Dalam artikel ini saya akan memadukan yang lama dengan yang baru, mengambil sesuatu yang primitif dan memberikan kehidupan baru ke dalamnya. Sass akan membantu merampingkan alur kerja Anda dan mungkin membantu mendemonstrasikan otomatisasi. Terkadang otomatisasi dapat membantu kreativitas.

Animasi, pendekatan lama

Saya jauh dari ahli dalam animasi, tapi saya tahu apa yang sebenarnya saya sukai: ketika semuanya bergerak. Ini sangat sederhana, saya seorang desainer web, dan animasi web adalah bagian dari pekerjaan saya. Dukungan terhadap animasi sudah ada dimana-mana sehingga kita dapat mengalihkan perhatian kita ke hal-hal yang lebih tinggi seperti tujuan dan makna animasi.

Meskipun animasi pada dasarnya dimaksudkan sebagai sesuatu yang ekspresif dan fleksibel, tidak semuanya berjalan mulus. Fakta bahwa animasi yang dibahas dalam artikel ini menjadi sangat populer jauh sebelum saya lahir agak menyedihkan.

Pesona abadi

“Lakukan semuanya sendiri, bahkan saat menggunakan komputer.”- Hayao Miyazaki

Studio Ghibli milik Hayo Miyazaki, yang telah menghasilkan banyak sekali karya hebat termasuk Spirited Away, Howl's Moving Castle, dan Princess Mononoke, tetap menggunakan teknik animasi tangan tradisional, animasi berlapis. Berbeda dengan CGI atau animasi keyframe yang menggunakan CSS, pendekatan ini membutuhkan lebih banyak waktu.

Miyazaki juga dikenal secara pribadi membuat mie ramen untuk staf animasinya pada larut malam, semua demi kesuksesan.

Namun, Studio Ghibli tidak bekerja dengan tangan karena merupakan semacam jimat masa lalu. Alasan mengapa animasi tetap populer sejak ditemukannya kamera adalah karena Anda dapat melihat kehidupan hanya dalam beberapa gerakan. Semua ini berlaku untuk animasi, di mana setiap frame digambar seluruhnya oleh seniman, bukan artefak seni vektor. Produk akhirnya jauh lebih kaya. Ada tradisi menggambar dengan tangan yang tak terucapkan, jadi setiap bingkai menyampaikan beberapa informasi.

Animasi halus di kiri dibuat menggunakan transformasi bingkai utama, sedangkan di kanan didasarkan pada tiga bingkai independen, satu demi satu. Pengguna Firefix mungkin memperhatikan bahwa properti transform-origin tidak diterapkan pada animasi di atas, itu semua karena bug.

SMIL yang tidak nyaman

Jika Anda mengatakan bahwa tidak ada teknologi di Internet untuk membuat animasi web berlapis, itu bohong. Dinamakan secara rumit Synchronized Multimedia Integration Language (SMIL), bahasa ini dirancang untuk membuat animasi. Jonathan Ingram memiliki tutorial bagus tentang penggunaan SMIL untuk membuat animasi berlapis dan berulang menggunakan karakter Mortal Kombat sebagai contoh:

< animate

id = "bingkai2"

atributNama = "tampilan"

nilai = "tidak ada; sebaris; tidak ada; tidak ada"

keyTimes = "0;0.33;0.66;1"

tahan = "1s"

mulai = "0 detik"

repeatCount = "tidak terbatas" / >

Elemen animate digunakan untuk menentukan status animasi elemen induk.

Namun, hal ini bukannya tanpa masalah serius. Meskipun merupakan klasifikasi yang cukup lama, SMIL masih belum didukung di IE. Selain itu, dukungan juga tidak direncanakan di IE12, 15, atau bahkan 38. Pada saat yang sama, bahasa tersebut menjadi usang dan dukungan di Chrome menurun. Paul Kinlan dari Google mengatakan bahwa Chrome 45 beta sebenarnya menutup mata terhadap peringatan penghentian SMIL.

Dukungan untuk SMIL terus menurun, dan menurut saya agak aneh menggunakan markup XML untuk membuat animasi. Saya terbiasa dengan animasi saya yang berada dalam file gaya terpisah, dan menurut saya itu ada di sana. Lagi pula, saat kita menganimasikan suatu elemen, kita hanya mengubah posisi visualnya, tetapi tidak memengaruhi markupnya. Ini hanya mungkin di JavaScript.
Sayangnya, tidak ada cara eksplisit atau cepat untuk membuat animasi berlapis di CSS, namun saya akan menjelaskan metode berdasarkan properti keyframe CSS yang jarang digunakan.

Mari kita mulai

@keyframe animation bekerja menggunakan properti animation-timing-function, Anda harus mengetahui beberapa fungsi timing. Misalnya, properti ease-in mengurangi kecepatan animasi saat mendekati penyelesaian.

Fungsi langkah() yang jarang digunakan juga menarik bagi kami karena mensimulasikan efek kedutan, seolah-olah animasi terdiri dari lapisan terpisah yang diputar satu demi satu. Misalnya, langkah(5) akan melakukan animasi yang cukup halus pada lima lapisan terpisah.

Semua nilai fungsisteps() mensimulasikan animasi keyframe; Tidak ada peralihan bingkai yang ajaib. Namun, jika Anda menggunakan langkah (1), Anda cukup beralih antar frame tanpa animasi apa pun. Dengan mengubah properti opacity dari 1 menjadi 0, kita dapat menampilkan dan menyembunyikan elemen animasi dalam satu langkah: ini dia, dan itu tidak. Ini adalah langkah yang sangat penting dalam membangun animasi berlapis yang akan saya buat.

Elemen sebagai lapisan terpisah

Sejauh ini, saya hanya khawatir tentang satu elemen, atau lapisan, yang dengan sendirinya tidak melakukan animasi apa pun dan tidak pantas mendapatkan mie Miyazaki itu. Inilah saat gambar itu muncul dan menghilang begitu saja.

Untuk membuat animasi yang lengkap, kita harus membuat lebih banyak gambar: sekumpulan lapisan yang akan membentuk animasi. Tahap ini sangat panjang dan tidak mudah, tetapi saya tidak akan mengeluh tentang hal ini: menggambar setiap lapisan adalah hal yang membuat jenis animasi ini istimewa. Nanti saya akan membutuhkan bantuan dalam menulis logika animasi.

Menandai

Untuk ini saya memerlukan SVG. Secara teknis, bisa ada banyak lapisan yang Anda suka, tetapi dalam SVG kita dapat dengan mudah mendefinisikan sekumpulan elemen jalur dan melapisinya di atas satu sama lain. Pada contoh di bawah ini saya membuat wadah animasi menggunakan elemen SVG (grup), di mana lapisan kita berada. Lapisan-lapisan ini harus ditulis sesuai urutan kemunculannya yang Anda inginkan.

< g class = "animation-name" >

< path d = "" > < / path >

< path d = > < / path >

< path d = "" > < / path >

< / g >

Membuat Lapisan

Ada banyak editor grafis untuk bekerja dengan SVG, tetapi Inkscape dibuat khusus untuk bekerja dengan format ini, dan juga menyertakan panel pengeditan XML bawaan. Ini akan membuat hidup kita lebih mudah. Dan itu juga gratis. Untuk mendemonstrasikan mekanismenya, mari kita lihat SVG dengan cepat. Buat dokumen Inkscape baru dan gambar tiga bentuk seperti gambar di bawah. Mereka tidak harus sama persis.

Tempatkan semua bentuk di atas satu sama lain dan sesuaikan ukuran dokumen dengan ukuran bentuk. Untuk melakukan ini pilih File->Document Properties dan kemudian Ubah ukuran halaman menjadi gambar atau pilihan. Pastikan tidak ada bentuk individual yang dipilih, jika tidak, ukuran dokumen akan disesuaikan dengan bentuk spesifik tersebut.

Kemudian pilih semua bentuk dan klik Object->Group, elemen grup akan dibuat . Kemudian, dengan grup yang masih dipilih, buka Edit &-> XML Editor dan berikan kelas.bentuk pada grup.

Bagus, sekarang simpan file SVG. Dari daftar, pilih SVG yang Dioptimalkan dan centang kotak di samping Aktifkan viewboxing. Sekarang SVG kita benar-benar siap untuk dianimasikan.

Catatan optimasi

Dengan menggunakan bentuk sederhana seperti milik kami, data SVG dijaga agar tetap minimum. Dalam hal ini, ukuran animasi SVG (termasuk CSS yang akan kita tulis nanti) hanya 2,3 KB. Sederhananya, semakin sederhana bentuk setiap lapisan, semakin banyak lapisan yang mampu Anda beli. Untuk menganimasikan gambar yang lebih kompleks, seperti coretan yang akan kita gunakan dalam artikel ini, saya sarankan menggunakan alat SVGOMG milik Jake Archibald.

Pelapisan

Seperti yang saya tulis di atas, menggunakan langkah (1) Anda dapat mengganti visibilitas suatu elemen menggunakan opacity. Anda tidak dapat mencapai efek yang sama dengan properti display, karena hanya membutuhkan nilai tertentu (tidak ada yang dianimasikan). Pertama, mari kita atur semua lapisan dalam wadah ke opacity:0.

Bentuk > * ( opasitas: 0; durasi animasi: 0,75 detik; jumlah iterasi animasi: tak terbatas; fungsi waktu animasi: langkah(1); )

Bentuk > * (

opacity: 0;

animasi - durasi: 0,75 detik;

animasi - iterasi - hitungan: tak terbatas;

animasi - waktu - fungsi : langkah ( 1 ) ;

Seperti halnya menyiapkan fungsi waktu langkah demi langkah, saya memilih jumlah iterasi yang tak terbatas, dengan durasi animasi 0,75 detik. Karena setiap frame muncul dalam jangka waktu yang sama, dan kita memiliki tiga frame, setiap frame akan muncul selama 0,25 detik, atau 4 frame per detik.

Jadi, seperti yang disebutkan, setiap frame muncul demi frame? Setiap elemen perlu disetel ke durasi animasi 0,75 detik, lalu menjalankan semua frame secara bersamaan, dengan lancar menampilkan satu frame di atas frame lainnya. Dengan tiga lapisan, masing-masing lapisan akan terlihat sepertiga waktunya. Saya menggunakan persentase (dalam sintaks @keyframe) dan menerapkan animasi berbeda untuk setiap anak ke-n.

@keyframes bentuk-1 ( 0% ( opacity: 1; ) 33.33333% ( opacity: 0; ) .shapes > :nth-child(1) ( nama-animasi: bentuk-1; ) @keyframes bentuk-2 ( 33.33333 % ( opacity: 1; ) 66.66667% ( opacity: 0; ) .shapes > :nth-child(2) ( nama-animasi: bentuk-2; ) @keyframes bentuk-3 ( 66.66667% ( opacity: 1; ) 100% ( opacity: 0; ) .shapes > :nth-child(3) ( nama-animasi: bentuk-3; )

@bentuk keyframe - 1 (

0 % {

opacity: 1;

33.33333 % {

opacity: 0;

Bentuk > : ke-n - anak (1 ) (

animasi - nama : bentuk - 1 ;

bentuk @keyframes - 2 (

33.33333 % {

opacity: 1;

66.66667 % {

opacity: 0;

Bentuk > : ke-n - anak (2 ) (

animasi - nama : bentuk - 2 ;

bentuk @keyframes - 3 (

66.66667 % {

opacity: 1;

100 % {

opacity: 0;

Bentuk > : ke-n - anak (3 ) (

animasi - nama : bentuk - 3 ;

Penyematan dan koneksi

Sekarang untuk membuat animasi GIF saya yang dapat diskalakan, saya akhirnya dapat menambahkan gaya ke file SVG. Karena saya tidak memiliki task runner di komputer saya, saya menggunakan autoprefixer versi online untuk menambahkan awalan vendor secara otomatis.

< svg viewBox = "0 0 100 100" >

< g class = "animation-name" >

< path d = "" > < / path >

< path d = "" > < / path >

< path d = "" > < / path >

< / g >

< / svg >

Beberapa, namun tidak semua browser akan memutar animasi meskipun Anda menyertakan SVG melalui tag img. Lebih dapat diandalkan untuk menggunakan objek.

< object type = "image/svg+xml" data = "path_to/shapes.svg" role = "img" aria - label = "shapes animation" >

< div role = "img" class = "shapes-fallback" aria - label = "shapes animation" > < / div >

< / object >

Perhatikan bahwa peran WAI-ARIA dengan nilai img dan atribut aria-label pada objek dan elemen DIV digunakan untuk presisi semantik. Saya tidak melakukan fallback untuk browser lama dengan img karena beberapa browser memuat tag ini selain SVG. Namun Anda tentu saja perlu menambahkan gambar latar belakang statis melalui CSS menggunakan properti background-image pada element.shapes-fallback.

Satu gambar, banyak animasi

Selain skalabilitas, SVG memiliki keunggulan lain dibandingkan GIF, yaitu kemampuan untuk menganimasikan bagian-bagian tertentu dari satu gambar - kecepatan animasi berbeda dan durasi berbeda. Dalam contoh hiu saya di bawah, ekor dan matanya dianimasikan dengan kecepatan berbeda dan jumlah lapisan berbeda.

Secara matematis, sesuatu yang menarik terjadi di sini: jika Anda memiliki dua animasi terpisah dalam file yang sama, total durasi animasi akan lebih lama daripada masing-masing komponen. Jadi, jika satu animasi terdiri dari tiga frame dan satu lagi terdiri dari empat frame, maka panjang totalnya akan menjadi 12 frame - tiga kali lebih panjang dari durasi terpanjang dari dua animasi terpisah.

Dalam GIF, di mana setiap frame dikaitkan langsung dengan sebuah lapisan, efek ini hanya dapat dicapai dengan menambahkan gambar baru. Dengan demikian, ukuran file bertambah.

Animasi variabel

Dalam contoh shark.svg saya, baik ekor yang bergoyang maupun mata yang berkedip menggunakan animasi simetris bergantian, di mana semua lapisan diputar terlebih dahulu ke depan, lalu ke belakang, dan seterusnya tanpa batas. Setiap elemen animasi berlapis mulai bergerak pada saat yang sama, menciptakan efek animasi tak terbatas menggunakan properti animation-direction: alternatif untuk setiap lapisan:

Ekor > * (arah animasi: alternatif; )

Ekor > * (

animasi - arah: bergantian;

Pendekatan ini menghemat berat. Untuk mendapatkan efek yang sama dalam GIF, Anda perlu menambahkan gambar dua kali: pertama dalam urutan normal, lalu secara terbalik.

Animasi yang benar-benar berlapis

Saya memulai artikel saya dengan kesimpulan bahwa animasi berlapis tradisional sulit dibandingkan dengan animasi keyframe modern. Sebelum munculnya animasi berlapis, setiap frame digambar secara keseluruhan—bukan hanya bagian animasi dari gambar. Jika Anda hanya menggambar bagian animasi pada lapisan, latar belakang statis dapat digunakan kembali. Selain menghemat waktu, pendekatan ini juga meningkatkan kelancaran.

SVG adalah format gambar berbasis teks yang dibagi menjadi banyak "subpohon" markup. Hal ini menjadikan format ini ideal untuk menggabungkan gambar statis dan animasi.

Otomatisasi dengan Sass

Animasi saya menjadi semakin canggih, dan membuat kelas animasi terpisah untuk setiap lapisan menjadi sedikit membosankan. Saya menyambungkan Sass untuk melakukan pekerjaan berat. Dengan menggunakan arahan @for dan beberapa perhitungan, saya dapat membuat animasi secara otomatis:

$cel: 6; $pecahan: 100 / $cel; @untuk $i dari 1 hingga $cels ( $nama: bentuk; $mulai: ($pecahan * $i) - $pecahan; @keyframes #($nama)-#($i) ( #($mulai * 1% ) ( opacity: 1; ) #(($start + $fraction) * 1%) ( opacity: 0; ) ) > :nth-child(#($i)) ( nama-animasi: #($name)- #($i); ) )

Dalam pelajaran sebelumnya di seri ini, kita melihat penggunaan grafik vektor SVG dalam HTML. Sekarang saatnya melihat animasinya SVG.

Dasar-dasar

Animasi SVG dilakukan menggunakan elemen :

Kami menambahkan elemen di dalam elemen , yang akan kita animasikan. Elemen berisi atribut berikut:

nama atribut: Ini mendefinisikan atribut yang akan berpartisipasi dalam animasi.

dari: atribut opsional. Mendefinisikan nilai awal, nilai saat ini digunakan secara default.

ke: Atribut ini menentukan arah animasi. Bergantung pada nilai yang ditentukan dalam atribut atributName, hasilnya mungkin berbeda. Pada contoh di atas, tinggi elemen akan berubah.

tahan lama: Menentukan durasi animasi. Nilai harus ditentukan dalam format Sintaks Nilai Jam. Misalnya, 02:33 sama dengan 2 menit 33 detik, dan 3 jam sama dengan 3 jam. Sebagai contoh, kami mendefinisikan durasi animasi sebagai 3 detik.

Kami melakukan hal yang sama dengan elemennya , tetapi itu akan menganimasikan atribut radius (r).

Elemen Bergerak

Untuk memindahkan elemen SVG Anda hanya perlu menentukan koordinat x dan y:

Dalam contoh kita memindahkan persegi panjang dari 0 ke 200 dalam 3 detik. Kami juga menambahkan atribut isi ke elemen . Atribut ini menentukan bagaimana animasi akan beraksi setelah selesai. Dalam contoh tersebut, nilai freeze memaksa elemen untuk tetap berada di tempat animasi berakhir.

Hal yang sama berlaku untuk elemennya , tapi untuk itu kita akan mengubah atribut cx atau cy:

Menganimasikan beberapa atribut

Tentu saja, di dalam elemen kita dapat mengatur perubahan hanya untuk satu atribut, tetapi untuk elemen itu sendiri kita dapat mendefinisikan beberapa. Seperti ini misalnya:

Di sini kita menganimasikan atribut untuk elemen tersebut - radius dan lebar goresan.

5 Januari 2014 pukul 16:27

Menganimasikan elemen jalur SVG

  • Pengembangan situs web,
  • Visualisasi data
  • tutorial

Saya rasa sudah banyak yang melihat review konsol game generasi baru dari Poligon (Media Vox). Di sinilah konsol digambar dengan gaya cetak biru:

Ulasannya terlihat keren, sangat tidak biasa dan baru. Anda dapat mengetahui di bawah ini bagaimana fitur utama ulasan diimplementasikan - animasi SVG, bagaimana melakukan hal serupa sendiri, dan kemampuan "rahasia" apa lagi yang disembunyikan SVG lama dalam hal animasi elemen jalur.

Interpolasi stroke-dasharray, teori

Secara umum teknik animasi garis seperti itu bukanlah hal baru, hanya saja sampai saat ini SVG dan segala sesuatu yang berhubungan dengannya, menurut saya, secara tidak adil dilupakan, namun untungnya situasinya berubah. Jadi, trik untuk menganimasikan elemen path dimungkinkan berkat properti stroke-dasharray dari elemen path. Properti ini memungkinkan Anda untuk mengatur parameter garis putus-putus, yaitu panjang guratan dan jarak antar guratan. Jika kita mengatur panjang guratan sama dengan seluruh panjang garis, kita mendapatkan garis padat biasa. Jika kita mengatur panjang guratan sama dengan nol, dan panjang celah kembali sama dengan seluruh panjang garis, maka kita mendapatkan garis tak kasat mata. Dan dengan menambah panjang goresan secara bertahap dengan panjang celah yang sama dengan panjang seluruh garis, kita dapat mensimulasikan gambarnya. Dengan pendekatan ini, pengundian akan dilakukan dari awal garis. Jika Anda tiba-tiba perlu menggambar dari akhir, maka Anda perlu menggunakan properti lain: stroke-dashoffset . Properti ini menentukan offset untuk pukulan pertama. Jadi, dengan mengurangi offset dan menambah panjang goresan, kita mendapatkan gambar dari ujung garis.

Orang-orang dari Media Vox mereka menggunakan opsi hybrid (yang menurut saya mubazir), omong-omong, Anda dapat (dan harus) membaca tentang bagaimana mereka melakukan ini di blog mereka: Desain fitur Polygon: Animasi SVG untuk kesenangan dan keuntungan.

Implementasi animasi SVG

DI DALAM Media Vox mereka menyarankan penggunaan requestAnimationFrame untuk animasi yang halus, tetapi kami memiliki tujuan yang sedikit berbeda, jadi kami akan mengambil rute yang lebih sederhana, menggunakan perpustakaan D3.js dan animasi berbasis durasi yang diterapkan di dalamnya.

Berikut adalah kode kerja sebenarnya yang digunakan untuk menganimasikan konsol dari awal artikel.

Antrian() .defer(d3.xml, "PS4.svg", "image/svg+xml") .await(siap); function ready(error, xml) ( //Menambahkan file svg kita ke dokumen HTML var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"), svgWidth = svg.attr("width"), svgHeight = svg.attr("height"); var path = svg.selectAll("path") .call(transisi) ; transisi fungsi(jalur) ( path.transition() .duration(5000) .attrTween("stroke-dasharray", tweenDash) .each("end", function() ( d3.select(this).call(transition) ; )); // loop tak terbatas ) fungsi tweenDash() ( var l = this.getTotalLength(), i = d3.interpolateString("0," + l, l + "," + l); // interpolasi goresan -dasharray attr fungsi pengembalian(t) ( kembalikan i(t); ); ) )


Mari kita mulai dengan hanya bergerak sepanjang garis, tanpa memutar terlebih dahulu.

Antrian() .defer(d3.xml, "wiggle.svg", "image/svg+xml") .await(siap); function ready(error, xml) ( //Menambahkan file svg kita ke dokumen HTML var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"); var path = svg.select("path#wiggle"), startPoint = pathStartPoint(path); var marker = svg.append("circle"); marker.attr(" r", 7).attr("transform", "translate(" + startPoint + ")"); transisi(); //Dapatkan titik awal jalur untuk menempatkan fungsi penanda pathStartPoint(path) ( var d = path.attr( "d"), dsplitted = d.split(" "); return dsplitted.split(","); ) fungsi transisi() ( marker.transition() .duration(7500) .attrTween("transform", TranslateAlong( path.node())) .each("end", transisi);// loop tak terbatas ) function TranslateAlong(path) ( var l = path.getTotalLength(); return function(i) ( return function(t) ( var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + p.y + ")";//Pindahkan penanda ) ) ) )
Di sini pathStartPoint(path) menarik koordinat awal garis dari atribut elemen path. Di TranslateAlong(path), koordinat penanda kita diatur menggunakan interpolator. Contohnya bisa dilihat di sini: Animasi penanda sepanjang elemen jalur SVG dengan D3.js. Anda juga dapat menggabungkan animasi gambar garis dan pergerakan penanda; mungkin terlihat seperti ini: Animasi penanda sepanjang elemen jalur SVG dengan D3.js II .

Mari kita memperumit tugas, menambahkan rotasi (yah, ubah penanda dari lingkaran menjadi sesuatu yang lebih menarik). Sebagai penanda kita akan memiliki roket dengan lebar 48 dan panjang 24. Karena titik jangkar default penanda adalah sudut kiri atas, kita perlu mengimbanginya agar tepat di tengah penanda. Anda juga perlu mempertimbangkan hal ini saat melakukan rotasi, karena ini juga terjadi secara default di pojok kiri atas. Tampaknya kami sudah menyelesaikan perpindahan tersebut. Sekarang mari kita langsung ke rotasi, disinilah definisi garis singgung akan membantu kita, kita akan menentukan sudut menggunakan arctangen.

Fungsi TranslateAlong(path) yang mendefinisikan interpolator akan terlihat seperti ini:

Fungsi TranslateAlong(path) ( var l = path.getTotalLength(); var t0 = 0; return function(i) ( return function(t) ( var p0 = path.getPointAtLength(t0 * l);//poin sebelumnya var p = path.getPointAtLength(t * l);////titik saat ini var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle untuk tangen t0 = t ; //Pergeseran pusat ke pusat roket var centerX = p.x - 24, centerY = p.y - 12; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " 24" + " 12 "+")"; ) ) )
Implementasinya dapat dilihat di sini.

Grafik SVG dapat dianimasikan menggunakan elemen animasi. Elemen-elemen ini awalnya ditentukan dalam spesifikasi animasi SMIL; Ini termasuk:

  • — memungkinkan Anda menyetel animasi untuk atribut dan properti skalar untuk jangka waktu tertentu;
  • adalah singkatan praktis untuk animasi yang memungkinkan Anda menetapkan nilai animasi ke atribut dan properti non-numerik, seperti properti visibilitas;
  • — menggerakkan elemen sepanjang jalur pergerakan;
  • - mengubah nilai warna atribut atau properti tertentu selama jangka waktu tertentu. Harap dicatat bahwa menggunakan elemen adalah praktik yang ketinggalan jaman dibandingkan dengan menggunakan elemen animasi untuk menentukan properti yang dapat mengambil nilai warna. Meskipun masih ada dalam spesifikasi SVG 1.1, spesifikasi yang sama dengan jelas menyatakan bahwa ia sudah tidak digunakan lagi; itu sepenuhnya dihapus dari spesifikasi SVG-2.

Selain elemen animasi yang ditentukan dalam spesifikasi SMIL, SVG menyertakan ekstensi yang kompatibel dengan spesifikasi animasi SMIL; ekstensi ini menyertakan atribut yang memperluas fungsionalitas elemen dan elemen animasi tambahan.

Ekstensi SVG meliputi:

  • — memungkinkan Anda menyetel animasi ke salah satu atribut transformasi SVG untuk jangka waktu tertentu, misalnya untuk atribut transform;
  • jalur (atribut) - Mengizinkan fungsi sintaksis data jalur SVG apa pun ditentukan dalam atribut jalur elemen animateMotion ( Animasi SMIL hanya mengizinkan sekumpulan sintaks data jalur SVG bawahan untuk digunakan dalam atribut jalur).

Kita akan membicarakan animateMotion di bagian selanjutnya:

  • - digunakan bersama dengan elemen animateMotion untuk merujuk pada jalur gerak yang harus digunakan, seperti jalur gerak. Elemen mpath disertakan di dalam elemen animateMotion, sebelum tag penutup;
  • titik kunci (atribut) - digunakan sebagai atribut animateMotion untuk memberikan kontrol yang tepat atas kecepatan pergerakan elemen animasi di sepanjang jalur;
  • memutar(atribut) - Digunakan sebagai atribut animateMotion untuk mengontrol apakah objek diputar secara otomatis sehingga titik sumbu x-nya berputar ke arah yang sama (atau berlawanan) dengan arah vektor tangen jalur gerak. Atribut ini adalah kunci untuk menciptakan pergerakan di sepanjang jalur sesuai keinginan Anda. Lebih lanjut tentang ini di bagian animateMotion.

Animasi SVG bisa mirip dengan animasi dan transisi CSS karena sifatnya. Cyframe dibuat, semuanya bergerak, warna berubah, dll. Namun, ia dapat melakukan beberapa hal yang tidak dapat dilakukan oleh animasi CSS. Saya akan membahasnya dalam panduan ini.

Untuk apa animasi SVG digunakan?

SVG dapat ditata dan dianimasikan menggunakan CSS (slide). Pada dasarnya, animasi transformasi atau transisi apa pun yang dapat diterapkan pada elemen HTML juga dapat diterapkan pada elemen SVG. Namun ada beberapa properti SVG yang tidak dapat dianimasikan melalui CSS, namun dapat dilakukan langsung melalui SVG.

Jalur SVG, misalnya, ditentukan oleh sekumpulan data (atribut d="") yang menentukan bentuk jalur tersebut. Data ini dapat diubah dan dianimasikan melalui SMIL, namun tidak melalui CSS.

Hal ini karena elemen SVG dideskripsikan menggunakan sekumpulan atribut yang dikenal sebagai atribut presentasi SVG. Beberapa atribut ini dapat disetel, dimodifikasi, dan dianimasikan menggunakan CSS, sementara atribut lainnya tidak.

Oleh karena itu, banyak efek animasi saat ini tidak dapat diimplementasikan menggunakan CSS. Kesenjangan ini dapat diisi dengan JavaScript atau dengan animasi SVG deklaratif yang berasal dari SMIL.

Jika Anda lebih suka menggunakan JavaScript, saya merekomendasikan snap.svg oleh Dmitry Baranovsky, yang disebut "jQuery for SVG".

Atau, jika Anda lebih menyukai pendekatan animasi yang lebih halus, Anda dapat menggunakan elemen SVG, yang akan kita bahas dalam tutorial ini!

Keuntungan lain dari animasi SMIL dibandingkan JS adalah JS tidak berfungsi ketika SVG disematkan sebagai img atau digunakan sebagai gambar latar belakang di CSS. Animasi SMIL berfungsi dalam kedua kasus ( atau diharapkan segera didukung oleh browser).

Menurut pendapat saya, ini merupakan keuntungan yang signifikan. Anda mungkin menemukan alasan lain untuk memilih SMIL. Artikel ini adalah panduan untuk membantu Anda memulai SMIL hari ini.

Dukungan browser dan alternatifnya

SMIL didukung secara luas oleh browser. Ia bekerja di semua browser kecuali Internet Explorer dan Opera Mini. Untuk informasi lengkap mengenai dukungan browser, Anda dapat merujuk ke tabel kompatibilitas atau “Dapatkah saya menggunakan”.

Jika Anda perlu menyediakan cadangan untuk animasi SMIL, Anda dapat memeriksa dukungan browser menggunakan Modernizr. Jika SMIL tidak didukung, Anda dapat memberikan semacam alternatif ( Animasi JavaScript, pendekatan alternatif, dll..).

Menentukan target animasi menggunakan xlink:href

Terlepas dari empat elemen animasi yang Anda pilih, Anda harus menentukan target animasi yang ditentukan oleh elemen tersebut.

Untuk menentukan target, Anda dapat menggunakan atribut xlink:href. Atribut tersebut mengambil referensi URI ke elemen yang menjadi objek animasi ini, dan karenanya akan berubah seiring waktu. Elemen target harus menjadi bagian dari fragmen dokumen SVG saat ini:

Jika Anda pernah berurusan dengan elemen animasi SVG sebelumnya, Anda mungkin menemukannya sebagai elemen bersarang di dalam elemen lain yang seharusnya dianimasikan. Ini disediakan oleh spesifikasi.

Jika atribut xlink:href tidak digunakan, maka elemen target akan menjadi elemen induk yang naik level pertama dari elemen animasi saat ini:

Jadi, jika Anda ingin " merangkum» animasi ke dalam elemen yang diterapkan, Anda dapat melakukan hal itu. Dan jika Anda ingin elemen animasi disimpan di tempat lain dalam dokumen, Anda dapat melakukannya dengan menentukan target untuk setiap elemen animasi menggunakan xlink:href - kedua metode bekerja sama baiknya.

Menentukan properti target animasi menggunakan atributName dan atributType

Semua elemen animasi juga berinteraksi dengan atribut lain: nama atribut. atributName digunakan untuk menentukan nama atribut yang Anda animasikan.

Misalnya saja jika Anda ingin mengatur animasi untuk posisi tengah pada sumbu x, Anda melakukannya dengan menentukan cx sebagai nilai atribut atributName.

atributName hanya menerima satu nilai, namun tidak menerima daftar nilai, karena Anda hanya dapat menganimasikan satu atribut dalam satu waktu. Jika Anda ingin menentukan animasi untuk lebih dari satu atribut, Anda harus menentukan lebih dari satu efek animasi untuk elemen tersebut.

Ini adalah sesuatu yang saya kurang suka, dan menurut saya di sinilah CSS memiliki keunggulan dibandingkan SMIL. Namun sekali lagi, karena nilai yang memungkinkan untuk atribut animasi lainnya ( lebih lanjut tentang itu nanti), masuk akal untuk mendefinisikan hanya satu nama atribut pada satu waktu, jika tidak, jika Anda menentukan beberapa nilai atribut lagi, nilai-nilai tersebut akan menjadi terlalu rumit untuk dikerjakan.

Saat menentukan nama atribut, Anda dapat menambahkan awalan XMLNS ( kependekan dari namespace XML) untuk menunjukkan namespace atribut.

Namespace juga dapat ditentukan menggunakan atribut atributType. Misalnya, beberapa atribut termasuk dalam namespace CSS (yang berarti atribut tersebut juga dapat ditemukan sebagai properti CSS), lainnya - namespace XML saja.

Berikut adalah tabel yang mencantumkan atribut-atribut tersebut. Tabel ini tidak mencakup semua atribut SVG, hanya atribut yang dapat diatur menggunakan CSS. Beberapa sudah tersedia saat ini sebagai properti CSS.

Jika nilai untuk atributType tidak disetel secara eksplisit atau disetel ke otomatis, browser harus terlebih dahulu mencari daftar properti CSS, dan jika tidak ada yang ditemukan, cari namespace XML default elemen tersebut.

Misalnya, cuplikan berikut menyetel animasi untuk opasitas persegi panjang SVG. Karena atribut opacity juga tersedia sebagai properti CSS, atributType disetel ke namespace CSS:

Kita akan melihat atribut animasi lainnya dalam contoh berikut. Semua atribut animasi bersifat umum untuk semua elemen animasi kecuali dinyatakan lain.

Mengatur animasi untuk mengubah atribut elemen dari satu nilai ke nilai lainnya seiring waktu, yang menunjukkan keadaan akhir: dari, oleh, ke, selama, dan isi

Mari kita mulai dengan memindahkan lingkaran dari satu tempat ke tempat lain. Kita akan melakukan ini dengan mengubah nilai atribut cx ( yang menentukan posisi pusatnya sepanjang sumbu x).

Untuk ini kami menggunakan elemen . Elemen ini digunakan untuk menganimasikan satu atribut satu kali. Atribut yang mengambil nilai numerik dan warna biasanya dianimasikan menggunakan . Anda dapat menemukan daftar atribut yang dapat dianimasikan di tabel ini.

Untuk mengubah nilai dari satu nilai ke nilai lainnya dalam jangka waktu tertentu, digunakan atribut from, to, dan dur. Selain itu, Anda juga dapat menentukan kapan animasi harus mulai menggunakan atribut mulai:

Pada contoh di atas, kita mendefinisikan sebuah lingkaran dan kemudian memanggil animasi pada lingkaran tersebut. Pusat lingkaran berpindah dari posisi semula pada koordinat 50 satuan ke suatu titik pada koordinat 450 satuan sepanjang sumbu x.

Kami mengatur atribut start menjadi click . Artinya lingkaran akan mulai bergerak setelah kursor mouse ditekan. Anda dapat mengatur atribut ini ke waktu tertentu. Misalnya, Begin="0s" akan memulai animasi segera setelah halaman dimuat.

Anda dapat menunda dimulainya animasi dengan menetapkan nilai waktu positif, misalnya, Begin = "2s" akan memulai animasi dua detik setelah halaman dimuat.

Yang lebih menarik lagi adalah Anda dapat menentukan atribut start dengan nilai seperti click + 1s , yang akan memulai animasi satu detik setelah mouse diklik!

Selain itu, Anda dapat menggunakan nilai lain yang memungkinkan Anda menyinkronkan animasi tanpa harus menghitung durasi dan penundaan animasi lainnya secara akurat. Lebih lanjut tentang ini nanti.

Atribut dur mirip dengan atribut durasi animasi CSS.

Atribut from dan to mirip dengan keyframe from dan to pada blok animasi CSS @keyframe:

@keyframes moveCircle ( dari ( /* nilai awal animasi */ ) ke ( /* nilai akhir animasi */ ) )

pengisian atribut( yang sayangnya, namanya sama dengan atribut isian lain yang menentukan warna isian elemen) mirip dengan properti animation-fill-mode, yang menentukan apakah elemen harus kembali ke keadaan semula setelah animasi selesai.

Maknanya di SVG mirip dengan yang digunakan di CSS, kecuali penggunaan nama yang berbeda:

  • membekukan: Nilai yang menentukan untuk membekukan status efek pada nilai durasi animasi terakhir. Efek animasi dibekukan hingga dokumen ditutup ( atau hingga animasi dimulai ulang);
  • hapus: Efek animasi dihilangkan ( tidak berlaku lagi), setelah menyelesaikan tindakan animasi yang ditentukan oleh durasi. Setelah animasi selesai, animasi tersebut tidak lagi diterapkan ke elemen target ( kecuali animasi dimulai ulang).

Coba ubah nilai dalam demo ini untuk melihat pengaruhnya terhadap animasi:
HTML:

CSS:

Hasil

Atribut by digunakan untuk menentukan offset relatif untuk animasi. Seperti namanya, Anda bisa menggunakannya untuk menentukan nilai yang akan menyebabkan animasi berubah.

Efek ini terutama hanya terlihat ketika Anda mengubah durasi animasi dari satu siklus ke siklus berikutnya, mirip dengan cara kerja fungsi CSSsteps().

Setara SVG dengan fungsi CSSsteps() adalah calcMode="discrete" . Kita akan membahas atribut calcMode="discrete" nanti.

Memulai ulang animasi menggunakan restart

Anda mungkin perlu memblokir animasi agar tidak dimulai ulang saat sedang aktif. Untuk tujuan ini, SVG menyediakan atribut restart.

Anda dapat mengaturnya ke salah satu dari tiga kemungkinan nilai:

  • selalu: Animasi dapat dimulai ulang kapan saja. Ini adalah standarnya;
  • WhenNotActive: Animasi hanya dapat dimulai ulang ketika tidak aktif ( yaitu setelah periode durasi animasi selesai). Upaya untuk memulai ulang animasi saat animasi sedang berlangsung akan diabaikan;
  • tidak pernah: Elemen tidak dapat dimulai ulang hingga wadah induknya dimulai ulang. ( Dalam kasus SVG, karena wadah induknya adalah fragmen dokumen SVG, animasi tidak dapat dimulai ulang hingga dokumen dimuat ulang.).

Nama animasi dan waktunya

Katakanlah kita ingin menganimasikan posisi dan warna lingkaran sehingga warnanya berubah di akhir animasi gerakan. Kita dapat melakukan ini dengan mengatur nilai awal animasi perubahan warna agar sama dengan durasi animasi gerakan; Inilah yang biasanya kita lakukan di CSS.

Namun, SMIL memiliki fitur penanganan acara yang hebat. Saya telah menyebutkan bahwa atribut start menerima nilai seperti click + 5s . Nilai ini disebut " arti dari acara tersebut“, dan dalam hal ini terdiri dari suatu peristiwa yang diikuti dengan “nilai jam”.

Bagian yang paling menarik di sini adalah bagian kedua - “arti jam”. Mengapa tidak disebut saja " nilai waktu"? Jawabannya adalah Anda dapat menggunakan nilai ini secara harfiah, seperti jam: Anda dapat menyetelnya ke "10 menit" atau "01:33", yang setara dengan " 1 menit 33 detik", atau bahkan "02:30:03" ( 2 jam, 30 menit dan 3 detik). Saat tulisan ini dibuat, nilai jam belum sepenuhnya diterapkan di sebagian besar browser.

Jadi jika pada demo sebelumnya kita menggunakan klik + 01:30, maka jika dukungan browser diterapkan, animasi akan dimulai 1 menit 30 detik setelah klik mouse.

Jenis nilai lain yang dapat diambil oleh atribut ini adalah ID animasi lain yang diikuti oleh penanda peristiwa. Jika Anda memiliki dua (atau lebih) efek animasi ( terlepas dari apakah mereka diterapkan pada elemen yang sama atau tidak!), dan Anda ingin menyinkronkannya sehingga yang satu dimulai bergantung pada tahap eksekusi yang lain, Anda dapat melakukan ini tanpa mengetahui durasi animasi lainnya.

Misalnya, pada contoh berikut, persegi panjang biru mulai bergerak 1 detik setelah animasi lingkaran dimulai. Hal ini dilakukan dengan memberikan ID pada setiap elemen animasi dan kemudian menggunakan ID tersebut dengan acara awal, seperti yang ditunjukkan dalam kode berikut:

mulai="circ-anim.begin + 1s" memberitahu browser untuk mulai menganimasikan persegi panjang 1 detik setelah animasi lingkaran dimulai.

Anda dapat melihat semuanya di demo ini:

HTML:

Klik pada lingkaran untuk memulai animasinya dan animasi persegi panjang 1 detik setelahnya.

CSS:

Hasil

Anda juga dapat memulai animasi persegi panjang ketika animasi lingkaran telah selesai menggunakan event end:

Anda bahkan dapat menjalankannya sebelum animasi lingkaran selesai:

Mengulangi animasi menggunakan repeatCount

Jika Anda ingin menjalankan animasi lebih dari sekali, Anda dapat melakukannya menggunakan atribut repeatCount. Anda dapat menentukan berapa kali Anda ingin mengulanginya atau menggunakan kata kunci tidak terbatas untuk mengulang animasi tanpa batas.

Jadi, jika kita ingin mengulang animasi lingkaran dua kali, kodenya akan terlihat seperti ini:

Anda dapat melihatnya di demo. Saya mengatur jumlah pengulangan untuk lingkaran menjadi 2 dan untuk persegi menjadi tidak terbatas.
HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Perhatikan bahwa animasi dimulai ulang dari nilai asli dari , bukan dari nilai yang dicapai saat perulangan berakhir. Sayangnya, SMIL tidak mengizinkan kita menentukan jalur bolak-balik antara nilai awal dan akhir seperti yang dapat kita lakukan dengan animasi CSS.

Dalam CSS, properti animation-direction menentukan apakah animasi harus diputar dalam arah yang berlawanan atau memulai setiap siklus dari titik nol.

Arti arah animasi: alternatif berarti loop animasi bernomor genap diputar dalam arah normal, dan loop animasi bernomor ganjil diputar dalam arah sebaliknya. Artinya loop pertama akan diputar dari awal hingga akhir, loop kedua akan diputar dari akhir ke belakang, loop ketiga akan diputar lagi dari awal hingga akhir, dan seterusnya.

Untuk melakukan ini di SMIL, Anda harus menggunakan JavaScript untuk mengubah nilai atribut from dan to. John McPartland dari Big Bite Creative beberapa waktu lalu menerbitkan sebuah artikel, yang menjelaskan bagaimana dia melakukan ini untuk animasi ikon menu yang sedang dia kerjakan.

Berikut adalah animasi hebat dan sederhana yang berulang tanpa batas waktu menggunakan penundaan, yang dibuat oleh Miles Elam:

HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Membatasi waktu pengulangan animasi menggunakan repeatDur

Menjalankan animasi tanpa henti dapat mengganggu atau merusak desain halaman jika dilakukan terus-menerus dalam jangka waktu lama.

Oleh karena itu, Anda mungkin merasa sangat berguna untuk dapat membatasi pengulangan animasi ke jangka waktu tertentu, dan menghentikan pengulangan animasi beberapa saat setelah dokumen dimuat - ini disebut waktu presentasi.

Waktu presentasi menunjukkan posisi pada skala waktu suatu fragmen dokumen tertentu yang terkait dengan awal keseluruhan dokumen. Ini ditentukan menggunakan atribut repeatDur.

Sintaksnya mirip dengan nilai jam, namun alih-alih dihitung dari peristiwa animasi atau interaksi lainnya, dalam hal ini waktu dihitung dari awal (pemuatan) dokumen.

Misalnya, cuplikan berikut akan menghentikan pengulangan animasi 1 menit 30 detik setelah dokumen dimulai (dimuat):

Dan ini adalah demo yang menggambarkan atribut ini:
HTML:

Hasil

Menyinkronkan animasi tergantung pada jumlah pengulangan

Sekarang mari kita kembali ke sinkronisasi antara kedua animasi tersebut. Faktanya, di SMIL Anda dapat menyinkronkan animasi sehingga satu animasi berjalan bergantung pada berapa kali animasi lainnya diulang.

Misalnya, Anda dapat memulai animasi setelah pengulangan ke-n yang lain, plus atau minus jangka waktu tertentu, yang juga dapat Anda atur.

Dalam contoh berikut, animasi persegi panjang dimulai pada iterasi kedua dari animasi lingkaran:

Sinkronisasi tergantung pada jumlah pengulangan saat ini tidak diterapkan di semua browser, oleh karena itu sayangnya versi demo tidak disediakan untuk bagian ini.

Mengelola nilai keyframe animasi: keyTimes dan nilai

Di CSS, kita dapat menentukan nilai yang harus diambil oleh properti animasi dalam bingkai utama tertentu saat animasi diputar.

Misalnya, jika Anda menentukan animasi untuk memindahkan elemen ke kiri, alih-alih menentukan offset untuk berubah langsung dari 0 hingga 300, Anda dapat menganimasikannya sehingga offset tersebut mengambil nilai tertentu dalam bingkai tertentu seperti ini :

@keyframes contoh ( 0% ( kiri: 0; ) 50% ( kiri: 320px; ) 80% ( kiri: 270px; ) 100% ( kiri: 300px; ) )

0%, 20%, 80%, dan 100% adalah bingkai animasi, dan nilai di setiap blok bingkai adalah nilai untuk masing-masing bingkai tersebut. Efek yang dijelaskan di atas merupakan salah satu elemen animasi bola memantul.

Di SMIL, Anda dapat mengelola nilai bingkai utama dengan cara yang sama, tetapi sintaksisnya sendiri sangat berbeda.

Untuk menentukan keyframe, atribut keyTimes digunakan. Dan untuk menentukan nilai properti animasi untuk setiap frame, digunakan atribut value. Konvensi penamaan di SMIL cukup mudah.

Jika kita kembali ke lingkaran bergerak dan menggunakan nilai yang mirip dengan keyframe CSS yang dijelaskan di atas, kodenya akan terlihat seperti ini:

Apa yang telah kita lakukan?

Hal pertama yang perlu diperhatikan adalah waktu dan nilai perantara dari bingkai utama ditentukan dalam bentuk daftar. Atribut keyTimes adalah daftar nilai waktu yang dipisahkan titik koma yang digunakan untuk mengontrol langkah-langkah animasi. Setiap kali dalam daftar sesuai dengan nilai dalam daftar atribut nilai, dan menentukan kapan nilai tersebut digunakan dalam fungsi animasi.

Setiap nilai waktu dalam daftar keyTimes ditentukan sebagai angka desimal dari 0 hingga 1 (inklusif), yang mewakili pergeseran waktu proporsional dalam pemutaran elemen animasi. Jadi keyTimes berfungsi sama seperti rekan-rekan CSS-nya, hanya saja kita mendefinisikannya sebagai desimal, bukan persentase.

Di bawah ini adalah demo untuk kode ini.
HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Perlu diperhatikan bahwa jika daftar nilai digunakan, animasi akan diterapkan sesuai dengan nilai yang ditentukan di dalamnya. Dalam hal ini, semua atribut from, to dan by akan diabaikan.

Mengontrol tempo animasi dengan penyesuaian khusus: calcMode dan keySplines

Saya akan kembali membandingkan CSS dan SMIL sekarang karena sintaks dan konsep SMIL akan lebih mudah dipahami jika Anda sudah familiar dengan animasi CSS.

Di CSS, Anda dapat mengganti pengaturan waktu animasi default dan menentukan fungsi penyesuaian khusus yang akan mengontrol animasi menggunakan properti fungsi pengaturan waktu animasi.

Fungsi pengaturan waktu dapat ditentukan dengan salah satu dari beberapa kata kunci yang telah ditentukan sebelumnya atau fungsi kubik b;zier. Yang terakhir dapat dibuat menggunakan alat seperti ini yang dikembangkan oleh Leia Verou.

Di SMIL, tempo animasi diatur menggunakan atribut calcMode. Secara default, nilainya untuk semua elemen animasi adalah linear, kecuali animateMotion ( kita akan membahasnya lagi nanti). Selain nilai linier, Anda juga dapat mengatur nilai berikut: diskrit, kecepatan, atau spline.

  • diskrit menentukan bahwa fungsi animasi berpindah dari satu nilai ke nilai lainnya tanpa interpolasi. Ini mirip dengan fungsi CSSsteps();
  • paced mirip dengan linear , kecuali bahwa ia mengabaikan nilai perantara dan mengubah waktu animasi yang ditentukan dalam keyTimes ;
  • spline menginterpolasi dari satu nilai dalam daftar nilai ke nilai lainnya sesuai dengan fungsi waktu yang ditentukan oleh spline Bezier kubik. Titik spline ditentukan dalam atribut keyTimes, dan titik transisi untuk setiap interval ditentukan dalam atribut keySplines.

Anda mungkin memperhatikan bahwa saya menyebutkan atribut baru: keySplines. Apa yang dilakukan atribut keySplines?

Sekali lagi ini mirip dengan CSS.

Di CSS, Anda dapat menentukan tempo animasi dalam setiap keyframe, alih-alih menentukan tempo animasi tunggal untuk keseluruhan animasi. Ini memberi Anda kontrol lebih besar atas bagaimana setiap frame animasi mengalir. Contoh penggunaan fungsi ini adalah membuat efek bola memantul. Bingkai utama untuknya mungkin terlihat seperti ini:

@keyframes bouncing ( 0% ( atas: 0; fungsi waktu animasi: kemudahan masuk; ) 15% ( atas: 200 piksel; fungsi waktu animasi: kemudahan keluar; ) 30% ( atas: 70 piksel; waktu animasi -fungsi: kemudahan masuk; ) 45% ( atas: 200 piksel; fungsi pengaturan waktu animasi: kemudahan masuk; ) 60% ( atas: 120 piksel; fungsi pengaturan waktu animasi: kemudahan masuk; ) 75% ( atas: 200 piksel ; fungsi pengaturan waktu animasi: kemudahan keluar; ) 90% ( atas: 170 piksel; fungsi pengaturan waktu animasi: kemudahan masuk; ) 100% ( atas: 200 piksel; fungsi pengaturan waktu animasi: kemudahan keluar; ) )

Alih-alih fungsi penyesuaian, kita dapat menggunakan fungsi kubik-bezier yang sesuai:

  • kemudahan masuk = kubik-bezier(0,47, 0, 0,745, 0,715);
  • kemudahan keluar = kubik-bezier(0,39, 0,575, 0,565, 1)

Mari kita mulai dengan menentukan interval waktu utama dan daftar nilai lingkaran oranye untuk menciptakan efek bola memantul yang sama:

Animasi akan dimulai saat mouse diklik pada elemen, dan terhenti segera setelah mencapai nilai akhir. Selanjutnya, untuk mengatur tempo setiap keyframe, kita akan menambahkan atribut keySplines.

Atribut keySplines mengambil sekumpulan b;zier breakpoint yang terkait dengan daftar keyTimes yang mendefinisikan fungsi Bézier kubik yang mengontrol interval pada tempo berbeda. Nilai atribut adalah daftar deskripsi titik kontrol yang dipisahkan titik koma.

Setiap deskripsi titik kontrol adalah sekumpulan empat nilai: x1 y1 x2 y2, yang menggambarkan koordinat titik kontrol b;zier untuk satu segmen waktu. Nilainya harus antara 0 dan 1, dan calcMode harus disetel ke spline , jika tidak, atribut akan diabaikan.

Daripada menggunakan fungsi kubik-bezier sebagai nilai, keySplines mengambil koordinat dua titik kontrol, yang digunakan untuk memplot kurva. Anda dapat melihat titik kontrol ini pada gambar di bawah, diambil dari alat Leah.

Tangkapan layar juga menunjukkan koordinat setiap titik, dengan setiap nilai koordinat memiliki warna yang sama dengan titik yang digambarkannya. Sedangkan untuk atribut keySplines, inilah nilai yang akan kita gunakan untuk menentukan tempo setiap keyframe animasi.

Di SMIL, nilai-nilai ini dapat dipisahkan dengan koma dengan spasi tambahan, atau hanya spasi. Nilai keyTimes yang menentukan segmen terkait adalah " titik referensi" b;zier dan nilai keySplines adalah breakpoint. Oleh karena itu, pos pemeriksaan harus disetel kurang dari keyTimes:


Jika kita kembali ke contoh bola memantul, koordinat titik kontrol untuk fungsi ease-in dan ease-out ditunjukkan pada gambar berikut:
Jadi, menerjemahkan semua ini ke dalam elemen animasi SVG, kita mendapatkan kode berikut:

Di bawah ini adalah demo, tetapi pastikan Anda menjalankannya di Firefox dan bukan Chrome karena versi terbaru memiliki bug yang mencegah demo berfungsi dengan benar:

HTML:

Klik pada lingkaran untuk memulai animasi.

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Jika Anda hanya ingin menentukan fungsi penyesuaian kecepatan umum untuk keseluruhan animasi, tanpa nilai perantara, Anda tetap harus menentukan bingkai utama menggunakan atribut keyTimes, namun Anda hanya perlu menentukan bingkai utama awal dan akhir, yaitu 0; 1 - tanpa nilai perantara.

Menambahkan dan mengumpulkan animasi: menambahkan dan mengumpulkan

Terkadang kita perlu mendefinisikan animasi yang dimulai dari akhir animasi sebelumnya; atau animasi yang menggunakan jumlah kumulatif animasi sebelumnya sebagai nilai untuk mulai diputar. Untuk melakukan ini, ada dua atribut dalam SVG, yang diberi nama dengan tepat: additive dan acquire .

Katakanlah Anda memiliki elemen yang lebarnya ingin Anda tambah, atau garis yang ingin Anda tambah panjangnya. Atau katakanlah Anda memiliki elemen yang ingin Anda pindahkan langkah demi langkah, pada interval tertentu. Fitur ini sangat berguna untuk mengulang animasi.

Seperti halnya animasi lainnya, Anda perlu menentukan nilai dari dan ke. Pada saat yang sama, saat Anda menyetel atribut aditif ke jumlah, masing-masing nilai ini akan dikaitkan dengan nilai asli dari atribut yang dianimasikan.

Jadi mari kita kembali ke lingkaran kita. Untuk itu, posisi awal cx adalah 50. Jika Anda menetapkan nilai dari = "0" hingga = "100" maka nol sebenarnya berarti nilai awal 50, dan 100 berarti nilai awal 50+100. Artinya, dalam praktiknya ternyata Anda menyetel “from="50″ to="150" .

Setelah melakukan ini, kita akan mendapatkan hasil sebagai berikut:

HTML:

Klik pada lingkaran untuk memulai animasi.

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Hanya itu yang dilakukan atribut aditif. Ini hanya menentukan apakah nilai from dan to akan dikaitkan dengan nilai atribut saat ini atau tidak. Atribut mengambil salah satu dari dua nilai: sum dan replace .

Nilai terakhir adalah default, dan ini biasanya berarti bahwa nilai dari dan ke yang diberikan akan menggantikan nilai saat ini/asli, yang pada akhirnya dapat menyebabkan elemen animasi tiba-tiba berubah posisi di awal animasi.

(Coba ganti sum dengan replace pada contoh di atas dan Anda akan melihat apa yang terjadi).

Namun, bagaimana jika kita ingin nilai-nilai tersebut ditambahkan sehingga loop animasi kedua dimulai di tempat yang pertama berakhir? Atribut akumulasi akan membantu kita dalam hal ini.

Atribut akumulasi mengontrol apakah nilai akhir atribut sebelumnya diperhitungkan. Secara default, nilainya adalah none , artinya ketika animasi diulang, animasi akan melakukannya dari awal, tidak termasuk akhir dari iterasi sebelumnya.

Namun, Anda dapat mengaturnya ke sum . Ini berarti bahwa setiap siklus animasi baru terkait dengan akhir siklus sebelumnya.

Jadi jika kita kembali ke animasi sebelumnya dan menentukan akumulasi = "jumlah" kita akan mendapatkan hasil sebagai berikut:
HTML:

Klik pada lingkaran untuk memulai animasi.

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Perhatikan bahwa atribut akumulasi diabaikan jika nilai atribut target tidak mendukung penambahan, atau jika elemen animasi tidak berulang. Ini juga akan diabaikan jika fungsi animasi ditentukan hanya dengan satu atribut to.

Menentukan akhir animasi menggunakan end

Selain menentukan kapan animasi harus dimulai, Anda juga dapat menentukan kapan harus berakhir melalui atribut end. Misalnya, Anda dapat mengatur agar animasi diulang tanpa batas waktu, lalu menghentikannya saat elemen lain mulai dianimasikan.

Atribut end mempunyai nilai yang sama dengan atribut start. Anda dapat menentukan nilai/interval waktu absolut atau relatif, nilai pengulangan, nilai peristiwa, dll.

Misalnya, dalam demo berikut, lingkaran oranye perlahan berpindah selama 30 detik ke sisi lain kanvas. Lingkaran hijau juga dianimasikan, tetapi animasi hanya dimulai ketika Anda mengkliknya.

Animasi lingkaran oranye akan berakhir ketika animasi lingkaran hijau dimulai - jadi ketika Anda mengklik lingkaran hijau, lingkaran oranye akan berhenti.

HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; )

Hasil

Tentu saja sinkronisasi animasi yang sama dapat dilakukan untuk dua animasi yang diterapkan pada elemen yang sama. Misalnya, kita menyiapkan animasi warna lingkaran yang warnanya berubah tanpa batas dari satu nilai ke nilai lainnya.

Dan kemudian animasi yang mengatur lingkaran agar bergerak saat Anda mengkliknya dengan kursor mouse. Sekarang kita akan mengatur agar perubahan warna berhenti setelah kita mengklik elemen tersebut dan elemen tersebut mulai bergerak.
HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; )

Hasil

Mendefinisikan interval animasi menggunakan beberapa nilai awal dan akhir

Faktanya, atribut awal dan akhir menerima daftar nilai yang dipisahkan koma. Setiap nilai dalam atribut awal akan memiliki nilai yang sesuai di atribut akhir, sehingga menciptakan interval animasi aktif dan tidak aktif.

Hal ini dapat diumpamakan sebagai mobil yang bergerak yang rodanya aktif atau tidak aktif selama beberapa waktu, bergantung pada apakah mobil tersebut bergerak atau diam.

Anda bahkan dapat membuat animasi mobil yang bergerak dengan menerapkan efek yang sesuai: satu untuk menggerakkan mobil atau memindahkannya sepanjang jalur yang menggunakan animasi tambahan dan kumulatif; yang kedua adalah memutar roda dengan interval yang selaras dengan gerakan.

Contoh pengaturan beberapa waktu mulai dan akhir animasi (yaitu interval) adalah demo berikut, di mana persegi panjang diputar pada interval tertentu, dari aktif ke tidak aktif.
(Mulai ulang demo jika Anda melewatkan animasinya).
HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; )

Hasil

Perlu dicatat bahwa dalam contoh di atas saya menggunakan elemen untuk mengatur rotasi persegi panjang. Kami akan membicarakan elemen ini lebih detail di bagian selanjutnya.

Perhatikan juga bahwa meskipun Anda menyetel repeatCount ke unlimited , nilai akhir akan diganti dan animasi tidak akan berulang tanpa batas.

Membatasi durasi suatu elemen menggunakan min dan maks

Sama seperti Anda dapat membatasi jumlah atau waktu pengulangan animasi, Anda juga dapat membatasi durasi animasi.

Atribut min dan max masing-masing menentukan nilai durasi animasi minimum dan maksimum. Mereka memberi kita kemampuan untuk menyesuaikan batas bawah dan atas durasi suatu elemen. Kedua atribut menerima jam.

min menentukan nilai durasi minimum animasi, diukur dengan durasi elemen. Nilai atribut ini harus lebih besar atau sama dengan 0 ( nilai default di mana durasi tindakan tidak dibatasi sama sekali).

Secara maks, nilai jam menentukan nilai nilai maksimum durasi tindakan, diukur dengan durasi elemen. Nilainya juga harus lebih besar dari 0. Nilai default untuk max tidak terbatas. Itu tidak membatasi durasi tindakan sama sekali.

Jika kedua atribut ditentukan, maka nilai max harus lebih besar atau sama dengan nilai min. Jika persyaratan ini tidak terpenuhi, maka kedua atribut tersebut akan diabaikan.

Tapi apa yang menentukan durasi aksi suatu elemen? Telah kami sebutkan sebelumnya bahwa ada durasi untuk pengulangan animasi, ini selain " durasi sederhana", yaitu durasi animasi tanpa pengulangan ( ditunjukkan dengan dur).

Jadi bagaimana semuanya bisa bekerja sama? Apa prioritas yang lebih tinggi? Dan bagaimana dengan atribut end, apakah itu menetapkan ulang nilai atau hanya mengakhiri animasi?

Semuanya bekerja seperti ini. Browser terlebih dahulu menghitung durasi aktivitas berdasarkan nilai dur, repeatCount, repeatDur, dan end. Setelah ini, penghitungan durasi dimulai berdasarkan nilai min dan maks.

Apabila hasil perhitungan tahap pertama berada dalam selang waktu yang dihitung pada tahap kedua, maka jangka waktu yang dihitung pertama tetap berlaku dan tidak berubah. Jika tidak, ada dua skenario yang mungkin terjadi:

  • Jika durasi perhitungan pertama lebih besar dari nilai maksimal, durasi elemen ditentukan sama dengan nilai maksimal;
  • Jika durasi yang dihitung terlebih dahulu kurang dari nilai min, maka durasi elemen akan sama dengan nilai min dan perilaku elemen adalah sebagai berikut;
  • Jika durasi pengulangan ( atau durasi sederhana jika elemen tersebut tidak diulang) elemen lebih besar dari min , maka elemen tersebut diputar ulang pada waktu standar (termasuk min ) dari durasi tindakan;
  • Jika tidak, elemen tersebut dimainkan selama durasi pengulangan standar ( atau durasi sederhana jika elemen tersebut tidak diulang), lalu terhenti dan tidak dikeluarkan sama sekali, bergantung pada nilai atribut isi.

Hal ini membawa kita pada pertanyaan tentang bagaimana sebenarnya browser menghitung durasi suatu aktivitas. Demi singkatnya, saya tidak akan menjelaskan secara detail.

Namun spesifikasinya berisi tabel yang sangat detail yang menunjukkan berbagai kombinasi atribut dur , repeatCount , repeatDur dan end serta bagaimana durasi animasi akan ditentukan berdasarkan setiap kombinasi.

Anda dapat melihat tabel ini dan mendapatkan informasi lebih lanjut dari bagian spesifikasi ini.

Terakhir, jika elemen didefinisikan untuk dimulai sebelum elemen induk dimulai ( misalnya hanya menggunakan nilai offset negatif), durasi minimum akan ditentukan oleh nilai yang dihitung pada tahap pertama, dan tidak akan dimasukkan dalam interval validitas elemen induk.

Artinya, nilai min tidak akan memberikan pengaruh nyata pada animasi elemen.

Contoh : mengubah jalur

Salah satu atribut yang dapat dianimasikan melalui SMIL ( tetapi Anda tidak dapat mengatur animasi melalui CSS), adalah atribut dari SVG-d( kependekan dari "data").

Atribut d berisi data yang mendefinisikan garis bentuk atau shape yang Anda buat. Data kerangka ini terdiri dari serangkaian perintah dan koordinat yang memberi tahu browser di mana dan bagaimana menggambar titik, busur, dan garis yang membentuk kerangka akhir.

Dengan menganimasikan atribut ini, kita dapat mengubah garis SVG dan membuat efek metamorfosis angka.

Namun, untuk dapat mentransformasikan bentuk, bentuk awal, akhir, dan semua titik tengah harus memiliki jumlah simpul/titik yang sama, dan harus muncul dalam urutan yang sama. Jika jumlah simpul dari berbagai bentuk tidak cocok, animasi tidak akan berfungsi.

Alasannya adalah transformasi bentuk sebenarnya dilakukan dengan memindahkan simpul dan menginterpolasi posisinya. Jadi jika salah satu simpul hilang atau tidak cocok dengan urutan keluaran keseluruhan, kontur tidak dapat diinterpolasi.

Untuk menganimasikan kerangka SVG, kita perlu menyetel atribut atributName ke d lalu menyetel nilai dari dan ke, yang menentukan bentuk awal dan akhir. Anda juga dapat menggunakan atribut nilai untuk menentukan nilai perantara apa pun yang harus diambil jalur saat diubah.

Demi singkatnya, saya tidak akan menjelaskan secara detail bagaimana melakukan ini. Sebagai gantinya, Anda bisa membaca artikel luar biasa ini oleh Noah Blon, di mana dia menjelaskan bagaimana dia menciptakan sosok transformasi menggunakan . Berikut demo animasi yang dibuat Noah:
HTML:

CSS:

body ( tinggi: 100vh; perataan teks: tengah; ukuran kotak: kotak perbatasan; padding-top: calc(50vh - 56px); ) img, svg ( tampilan: blok sebaris; perataan vertikal: tengah; ) svg ( tinggi: 38 piksel; lebar: 38 piksel; tampilan: blok sebaris; )

// Memasukkan gambar membantu menjaganya tetap sinkron $(document).ready(function())( $("img").attr("src", "http://dab1nmslvvntp.cloudfront.net/wp-content/ unggahan /2014/08/1407310358spinner-cropped.gif"); ));

Hasil

Dan berikut contoh morphing lainnya yang dilakukan Felix Ornoy:
HTML:

CSS:

Hasil

Anda bahkan dapat menggunakan jalur transformasi untuk memotong latar belakang di sekitarnya dan menentukan gambar tertentu. Berikut ini contoh dari Heather Bushel:
HTML:

SCSS:

$dasar: #C8C8A9; $utama: #FE4365; body ( latar belakang: $base; perataan teks: tengah; ) svg ( posisi: absolut; atas: 50%; kiri: 50%; margin-atas: -60px; margin-kiri: -60px; ) .logo ( isi: $primary; ) .clip ( animasi: slide 8s tak terbatas; ) @keyframes slide ( dari ( transform: TranslateY(-135px); ) 50% ( transform: TranslateY(-5px); ) ke ( transform: TranslateY(-135px) ; ) )

Hasil

Animasi Sepanjang Jalur Gratis: Elemen

- ini adalah elemen favorit saya dari animasi SMIL. Anda dapat menggunakannya untuk memindahkan elemen di sepanjang jalur. Anda dapat menentukan jalur gerak menggunakan salah satu dari dua metode yang akan saya ceritakan sekarang, lalu mengatur elemen untuk bergerak di sepanjang jalur tersebut.

Elemen mengambil atribut yang sama dengan elemen yang disebutkan sebelumnya, ditambah tiga atribut lainnya: keyPoints,rotate, dan path. Selain itu, ada satu perbedaan yang berkaitan dengan atribut calcMode. Untuk elemen defaultnya bersifat mondar-mandir, bukan linier.

Menentukan jalur pergerakan menggunakan atribut path

Atribut path digunakan untuk menunjukkan jalur pergerakan. Itu direpresentasikan dalam format yang sama dan diinterpretasikan dengan cara yang sama seperti atribut d untuk elemen path.

Efek dari menganimasikan gerakan sepanjang jalur adalah menambahkan matriks transformasi tambahan ke matriks objek terkait saat ini, yang memungkinkan untuk menentukan pergerakan objek sepanjang sumbu x dan y dari sistem koordinat pengguna saat ini dengan menghitung Nilai X dan Y untuk setiap momen dalam waktu.

Dengan kata lain, jalur yang ditentukan dihitung relatif terhadap posisi elemen saat ini, menggunakan data jalur untuk mengubah elemen menjadi salinannya yang sesuai dengan posisi jalur berbeda.

Kita ingin menganimasikan lingkaran kita agar bergerak di sepanjang jalur yang terlihat seperti ini:


Kode yang diperlukan untuk membuat lingkaran bergerak sepanjang jalur ini adalah sebagai berikut:

Ada satu hal yang saya ingin menarik perhatian Anda: koordinat pada data jalur. Jalur dimulai dengan perpindahan (M) ke suatu titik dengan koordinat (0, 0), setelah itu mulai menggambarkan kurva (c) ke titik lain.

Penting bagi Anda untuk memahami bahwa titik (0, 0) sebenarnya adalah posisi awal lingkaran, terlepas dari di mana titik tersebut berada pada awal animasi gerakan - titik tersebut BUKAN di sudut kiri atas sistem koordinat. Seperti yang kami sebutkan di atas, koordinat atribut path terikat pada posisi elemen saat ini!

Output dari kode di atas akan menjadi seperti berikut:
HTML:

CSS:

* ( ukuran kotak: kotak perbatasan; ) .cont ( tinggi: 100vh; padding: 20vmin; -webkit-filter: kontras(10); warna latar: putih; ) svg ( lebar: 100%; tinggi: 100% ; opacity: 0,9; -webkit-filter: blur(3px);)

Hasil

Jika Anda menentukan awal jalur pada suatu titik dengan koordinat selain (0, 0), maka lingkaran akan melakukan lompatan tajam ke titik pada koordinat yang ditentukan sebelum animasi dimulai.

Misalnya, Anda menggambar jalur di Illustrator lalu mengekspor data jalur tersebut untuk digunakan sebagai jalur gerak ( inilah yang saya lakukan pertama kali saya bekerja dengan elemen ini); jalur yang diekspor mungkin terlihat seperti ini:

Titik awal jalur dalam hal ini adalah (100.4, 102.2). Jika kita menggunakan data ini sebagai jalur gerak, lingkaran akan tiba-tiba melompat sekitar 100 unit ke kanan dan 102 unit ke bawah sebelum animasi dimulai, dan kemudian mulai bergerak di sepanjang jalur relatif terhadap posisi baru. Oleh karena itu, periksa data dengan cermat saat menyiapkan jalur gerak untuk animasi.

Atribut dari, oleh, ke dan nilai ( jika digunakan) menunjukkan bentuk kanvas saat ini, yang mewakili jalur gerakan.

Menentukan jalur gerak menggunakan elemen

Ada juga cara lain untuk menentukan lintasan pergerakan. Daripada menggunakan atribut jalur terkait, Anda dapat merujuk ke jalur eksternal menggunakan elemen tersebut . - elemen anak dari elemen , ia dapat terhubung ke jalur eksternal menggunakan atribut xlink:href:

Lintasan pergerakan dapat didefinisikan di mana saja dalam dokumen; itu bahkan dapat didefinisikan di dalam suatu elemen dan tidak ditampilkan di kanvas sama sekali. Contoh berikut menampilkan jalur karena dalam banyak kasus Anda mungkin ingin menampilkan jalur sepanjang elemen bergerak.

Harap dicatat bahwa menurut spesifikasi:

Berbagai titik (x, y) dari bentuk memberikan matriks transformasi CTM tambahan untuk berhubungan dengan objek, menghasilkan pergerakan sepanjang sumbu x dan y dari sistem koordinat pengguna saat ini melalui perhitungan nilai bentuk (x, y) ​untuk setiap segmen waktu. Dengan cara ini, objek terkait dipindahkan selama periode waktu tertentu, dengan jalur pergerakan objek bergeser ke sistem koordinat asli pengguna saat ini. Transformasi tambahan diterapkan pada transisi transformasi apa pun, berkat properti transform elemen target, atau pada transisi animasi apa pun dari atribut tersebut, berkat elemen animateTransform dari elemen target.

Sekali lagi, lingkaran "berkembang biak" atau "berubah" menjadi lingkaran lain di titik lain, sesuai dengan koordinat data jalur.

Pada contoh berikut kita memiliki jalur di tengah kanvas. Lingkaran ditempatkan di awal jalan. Namun, ketika jalur ini diterapkan, lingkaran tidak mulai bergerak dari posisinya saat ini. Untuk pemahaman yang lebih baik, tonton versi demonya. Klik pada lingkaran untuk menganimasikannya.

HTML:

Klik pada lingkaran untuk memulai animasi.

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Lihat bagaimana lingkaran mengikuti bentuk yang sama tetapi di lokasi yang berbeda? Hal ini dikarenakan posisi lingkaran diubah sesuai dengan nilai data jalur.

Salah satu cara untuk mengatasi masalah ini adalah dengan mengatur lingkaran pada (0, 0) sehingga ketika data jalur digunakan untuk mentransformasikannya, lingkaran tersebut mulai bergerak dan bergerak sesuai yang diharapkan.

Cara lain adalah dengan menerapkan transformasi yang "mengatur ulang" koordinat lingkaran sehingga disetel ke nol sebelum jalur diterapkan.

Di bawah ini adalah versi modifikasi dari demo di atas yang menggunakan jalur tertutup dan mengulangi animasi gerakan berkali-kali.

HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Mendefinisikan Ulang Aturan

Karena ada beberapa cara untuk melakukan hal yang sama untuk animateMotion, masuk akal untuk mengesampingkan aturan untuk menentukan nilai mana yang akan diganti dengan nilai lain.

Ganti aturan untuk animateMotion :

  • Saat mendefinisikan jalur gerak, elemen mpath menggantikan atribut path, yang pada gilirannya mengesampingkan nilai, dan nilai mengesampingkan dari, oleh, dan ke;
  • Sedangkan untuk mendefinisikan titik yang sesuai dengan atribut keyTimes, atribut keyPoints menggantikan atribut path, path menimpa nilai, dan nilai menimpa dari, oleh, dan ke.

Mengatur orientasi elemen sepanjang jalur gerak menggunakan memutar

Dalam contoh kita sebelumnya, elemen yang kita atur animasinya agar bergerak sepanjang jalur adalah lingkaran. Namun bagaimana jika kita menganimasikan elemen yang memiliki orientasi tertentu, misalnya ikon mobil?

Ikon mobil pada contoh berikut dibuat oleh Freepik.

Dalam contoh ini, saya mengganti lingkaran dengan grup dengan pengenal "mobil", yang berisi elemen yang membentuk grup tersebut.

Kemudian untuk menghindari permasalahan perpindahan jalur tersebut di atas, saya menerapkan transformasi pada mobil yang menempuh jarak tertentu sehingga posisi awal ditetapkan pada (0, 0).

Nilai-nilai di dalam transformasi sebenarnya adalah koordinat titik di mana lintasan pertama mobil mulai diletakkan ( segera setelah perintah pindah M).

Kemudian mobil mulai bergerak sepanjang lintasan. Tapi... beginilah penampakan gerakan ini:
HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Orientasi kendaraan tetap dan tidak berubah pada titik mana pun sepanjang lintasan. Untuk mengubahnya kita perlu menggunakan atributrotate.

Atribut memutar mengambil salah satu dari tiga nilai:

  • auto : menandakan benda diputar miring ke arah ( itu. vektor singgung) lintasan pergerakan;
  • auto-reverse : menandakan benda diputar miring terhadap arah ( itu. vektor singgung) lintasan pergerakan ditambah 180 derajat;
  • number: Menentukan bahwa transformasi rotasi konstan diterapkan pada elemen target, dengan sudut rotasi sama dengan angka yang ditentukan dalam derajat.

Untuk mengatur orientasi mobil pada contoh di atas, kita akan mulai dengan mengatur nilai rotasi ke auto . Dan kami mendapatkan hasil sebagai berikut:

HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Jika ingin mobil bergerak ke luar area jalur, hal ini dilakukan dengan menggunakan nilai auto-reverse.

Klik pada lingkaran untuk menganimasikannya.

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Ini jauh lebih baik, tapi kita masih mempunyai satu masalah: mobil melaju terbalik! Untuk mengubahnya, kita harus membaliknya sepanjang sumbu y. Hal ini dapat dilakukan dengan menskalakan dengan faktor "-1" sepanjang sumbu ini.

Jadi jika kita menerapkan transformasi ke g dengan ID car , mobil akan bergerak sesuai keinginan kita. Transformasi skala seharusnya hanya bergantian dengan transformasi yang kita terapkan sebelumnya.

Dan demo terakhirnya akan terlihat seperti ini:
HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) p ( warna: #aaa; perataan teks: tengah; margin: 2em 0; )

Hasil

Mengontrol jarak animasi dari jalur gerak menggunakan keyPoints

Atribut keyPoints memungkinkan kita menentukan jarak dari jalur gerak untuk setiap nilai keyTimes yang ditentukan. Jika atribut keyPoints ditentukan, ini menyebabkan keyTimes diterapkan ke nilai keyPoints, bukan ke titik yang ditentukan dalam larik atribut nilai atau titik atribut jalur.

keyPoints mengambil daftar nilai desimal yang dipisahkan titik koma dari 0 hingga 1 dan menentukan seberapa jauh objek harus bergerak dari jalur gerak pada waktu yang ditentukan oleh nilai keyTimes yang sesuai.

Perhitungan jarak ditentukan oleh algoritma browser. Setiap nilai berikutnya dalam daftar sesuai dengan nilai dalam daftar atribut thekeyTimes. Jika daftar keyPoints ditentukan, daftar tersebut harus berisi jumlah nilai yang sama persis dengan daftar keyTimes.

Atribut keyPoints tidak didukung di Chrome dan Firefox pada saat penulisan ini. Itu belum diimplementasikan, sama seperti bagian lain dari spesifikasi yang saya sebutkan sebelumnya.

Memindahkan teks sepanjang jalur sewenang-wenang

Memindahkan teks di sepanjang jalur kustom berbeda dengan memindahkan elemen SVG lainnya di sepanjang jalur. Untuk menganimasikan teks, Anda perlu menggunakan elemen tersebut , tapi tidak .

Pertama, mari letakkan beberapa teks di sepanjang jalur. Hal ini dapat dilakukan dengan menyarangkan sebuah elemen di dalam elemen .

Teks yang akan ditempatkan di sepanjang jalur akan ditentukan di dalam elemen , bukan sebagai anak .

textPath kemudian akan mereferensikan jalur sebenarnya yang ingin kita gunakan, seperti yang kita lakukan pada contoh sebelumnya. Jalurnya juga dapat ditampilkan di kanvas atau ditentukan secara internal . Lihat kode di bawah ini:
HTML:

Teks ditempatkan di sepanjang jalur.

CSS:

Hasil

Untuk menganimasikan teks yang bergerak di sepanjang jalur ini, kita akan menggunakan elemen untuk menganimasikan atribut startOffset.

startOffset menampilkan offset teks di sepanjang jalur. 0% adalah awal dari perjalanan; 100% adalah akhir. Jadi jika misalnya offset diatur ke 50%, teks akan dimulai di tengah jalur. Saya rasa Anda sudah menebak apa yang akan kita lakukan selanjutnya.

Dengan menganimasikan startOffset kita akan menciptakan efek teks bergerak di sepanjang jalur. Lihatlah kode untuk demo berikut.

HTML:

Teks ditata di sepanjang jalan.

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; ) teks ( isi: deepPink; ukuran font: 2em; )

Hasil

Transformasi Animasi: Elemen

Elemen menganimasikan atribut transformasi elemen target, sehingga memungkinkan animasi mengontrol pergerakan, penskalaan, rotasi, dan/atau kemiringannya. Ia menerima atribut yang sama yang terdaftar untuk elemen tersebut , ditambah atribut tambahan: type .

Atribut type digunakan untuk menentukan tipe transformasi yang kita animasikan. Dibutuhkan satu dari lima nilai: terjemahkan, skala, putar, skewX dan miringY .

Atribut dari, oleh, dan ke mengambil nilai yang dinyatakan menggunakan sintaks yang sama yang tersedia untuk jenis konversi ini:

  • + Untuk type="translate" , setiap nilai individual dinyatakan sebagai [,];
  • + Untuk type="scale" , setiap nilai individual dinyatakan sebagai [,];
  • + Untuk type="rotate", setiap nilai individual dinyatakan sebagai [ ];
  • + Untuk type="skewX" dan type="skewY" , masing-masing nilai dinyatakan sebagai .

Mari kita kembali ke demo sebelumnya dimana kita memutar persegi panjang merah muda menggunakan elemen . Kode untuk rotasinya terlihat seperti ini:

Atribut from dan to menunjukkan sudut rotasi (awal dan akhir) dan pusat rotasi. Untuk keduanya, pusat putarannya tetap sama tentunya. Jika Anda tidak menentukan bagian tengahnya, itu akan menjadi sudut kiri atas kanvas SVG. Demo untuk kode di atas terlihat seperti ini:
HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; )

Hasil

Di bawah ini adalah contoh menyenangkan lainnya dengan satu animateTransform yang dibuat oleh Gabriel:

HTML:

CSS:

* ( margin: 0; padding: 0; ) html, body ( tinggi: 100%; ) body ( latar belakang: #FC0; ) svg ( posisi: tetap; atas: 20%; tinggi: 60%; kiri: 20%; lebar: 60%; )

Hasil

Menganimasikan satu transformasi cukup sederhana, namun segalanya bisa menjadi sangat rumit dan membingungkan ketika kita mengaktifkan beberapa transformasi. Terutama karena satu elemen animateTransform dapat menimpa elemen lainnya, jadi alih-alih serangkaian efek yang konsisten, kita mungkin akan mendapatkan sesuatu yang benar-benar berlawanan.

Hal ini ditambah dengan betapa rumitnya sistem koordinat dan transformasi SVG. Ada banyak sekali kasus khusus yang berbeda, dan pembahasannya berada di luar cakupan artikel ini.

Untuk mengubah SVG, saya sarankan menggunakan transformasi CSS. Solusi terbaru berfungsi baik dengan SVG, jadi Anda mungkin tidak memerlukan SMIL sama sekali untuk menganimasikan transformasi di SVG.

Elemen

Elemen set menyediakan cara sederhana untuk menetapkan nilai suatu atribut untuk waktu tertentu. Ini mendukung semua jenis atribut, termasuk atribut yang tidak dapat diinterpolasi, seperti string dan boolean.

Elemen set tidak dapat ditambahkan. Atribut yang ditambahkan dan diakumulasikan tidak diperbolehkan, dan akan diabaikan jika ditentukan.

Karena digunakan untuk menyetel elemen ke nilai tertentu untuk waktu tertentu, ia tidak menerima semua atribut yang dijelaskan sebelumnya dalam tutorial ini. Misalnya, tidak mengandung atribut from atau by karena nilainya tidak berubah secara progresif selama periode waktu tertentu.

Untuk elemen set, Anda dapat menentukan elemen target, nama dan tipe atribut, nilai to, dan animasi pengaturan waktu, yang dapat dikontrol dengan: mulai, selama, akhir, min, maks, mulai ulang, repeatCount, repeatDur dan isi.

Di bawah ini adalah contoh yang mengatur warna persegi panjang yang berputar menjadi biru setelah klik mouse. Warnanya tetap biru selama 3 detik dan kemudian kembali ke nilai aslinya. Setiap kali Anda mengklik persegi panjang, animasi akan dimulai dan warnanya akan berubah selama 3 detik.

HTML:

CSS:

svg ( batas: 3px solid #eee; tampilan: blok; margin: 1em otomatis; )

Hasil

Elemen, atribut, dan properti yang dapat dianimasikan

Tidak semua atribut SVG bisa dianimasikan, dan tidak semua atribut yang bisa dianimasikan bisa dianimasikan menggunakan semua elemen animasi.

Untuk daftar lengkap semua atribut yang dapat dianimasikan, dan elemen mana saja yang dapat digunakan untuk menganimasikannya, silakan merujuk ke bagian ini dari spesifikasi animasi SVG.

Kesimpulan

SMIL memiliki banyak potensi, dan saya hanya membahas beberapa prinsip dasar dan aspek teknis saja. Anda dapat membuat banyak efek mengesankan menggunakan spesifikasi, terutama dengan morphing dan transformasi bentuk.

  • tutorial

Saya rasa sudah banyak yang melihat review konsol game generasi baru dari Poligon (Media Vox). Di sinilah konsol digambar dengan gaya cetak biru:

Ulasannya terlihat keren, sangat tidak biasa dan baru. Anda dapat mengetahui di bawah ini bagaimana fitur utama ulasan diimplementasikan - animasi SVG, bagaimana melakukan hal serupa sendiri, dan kemampuan "rahasia" apa lagi yang disembunyikan SVG lama dalam hal animasi elemen jalur.

Interpolasi stroke-dasharray, teori

Secara umum teknik animasi garis seperti itu bukanlah hal baru, hanya saja sampai saat ini SVG dan segala sesuatu yang berhubungan dengannya, menurut saya, secara tidak adil dilupakan, namun untungnya situasinya berubah. Jadi, trik untuk menganimasikan elemen path dimungkinkan berkat properti stroke-dasharray dari elemen path. Properti ini memungkinkan Anda untuk mengatur parameter garis putus-putus, yaitu panjang guratan dan jarak antar guratan. Jika kita mengatur panjang guratan sama dengan seluruh panjang garis, kita mendapatkan garis padat biasa. Jika kita mengatur panjang guratan sama dengan nol, dan panjang celah kembali sama dengan seluruh panjang garis, maka kita mendapatkan garis tak kasat mata. Dan dengan menambah panjang goresan secara bertahap dengan panjang celah yang sama dengan panjang seluruh garis, kita dapat mensimulasikan gambarnya. Dengan pendekatan ini, pengundian akan dilakukan dari awal garis. Jika Anda tiba-tiba perlu menggambar dari akhir, maka Anda perlu menggunakan properti lain: stroke-dashoffset . Properti ini menentukan offset untuk pukulan pertama. Jadi, dengan mengurangi offset dan menambah panjang goresan, kita mendapatkan gambar dari ujung garis.

Orang-orang dari Media Vox mereka menggunakan opsi hybrid (yang menurut saya mubazir), omong-omong, Anda dapat (dan harus) membaca tentang bagaimana mereka melakukan ini di blog mereka: Desain fitur Polygon: Animasi SVG untuk kesenangan dan keuntungan.

Implementasi animasi SVG

DI DALAM Media Vox mereka menyarankan penggunaan requestAnimationFrame untuk animasi yang halus, tetapi kami memiliki tujuan yang sedikit berbeda, jadi kami akan mengambil rute yang lebih sederhana, menggunakan perpustakaan D3.js dan animasi berbasis durasi yang diterapkan di dalamnya.

Berikut adalah kode kerja sebenarnya yang digunakan untuk menganimasikan konsol dari awal artikel.

Antrian() .defer(d3.xml, "PS4.svg", "image/svg+xml") .await(siap); function ready(error, xml) ( //Menambahkan file svg kita ke dokumen HTML var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"), svgWidth = svg.attr("width"), svgHeight = svg.attr("height"); var path = svg.selectAll("path") .call(transisi) ; transisi fungsi(jalur) ( path.transition() .duration(5000) .attrTween("stroke-dasharray", tweenDash) .each("end", function() ( d3.select(this).call(transition) ; )); // loop tak terbatas ) fungsi tweenDash() ( var l = this.getTotalLength(), i = d3.interpolateString("0," + l, l + "," + l); // interpolasi goresan -dasharray attr fungsi pengembalian(t) ( kembalikan i(t); ); ) )


Mari kita mulai dengan hanya bergerak sepanjang garis, tanpa memutar terlebih dahulu.

Antrian() .defer(d3.xml, "wiggle.svg", "image/svg+xml") .await(siap); function ready(error, xml) ( //Menambahkan file svg kita ke dokumen HTML var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"); var path = svg.select("path#wiggle"), startPoint = pathStartPoint(path); var marker = svg.append("circle"); marker.attr(" r", 7).attr("transform", "translate(" + startPoint + ")"); transisi(); //Dapatkan titik awal jalur untuk menempatkan fungsi penanda pathStartPoint(path) ( var d = path.attr( "d"), dsplitted = d.split(" "); return dsplitted.split(","); ) fungsi transisi() ( marker.transition() .duration(7500) .attrTween("transform", TranslateAlong( path.node())) .each("end", transisi);// loop tak terbatas ) function TranslateAlong(path) ( var l = path.getTotalLength(); return function(i) ( return function(t) ( var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + p.y + ")";//Pindahkan penanda ) ) ) )
Di sini pathStartPoint(path) menarik koordinat awal garis dari atribut elemen path. Di TranslateAlong(path), koordinat penanda kita diatur menggunakan interpolator. Contohnya bisa dilihat di sini: Animasi penanda sepanjang elemen jalur SVG dengan D3.js. Anda juga dapat menggabungkan animasi gambar garis dan pergerakan penanda; mungkin terlihat seperti ini: Animasi penanda sepanjang elemen jalur SVG dengan D3.js II .

Mari kita memperumit tugas, menambahkan rotasi (yah, ubah penanda dari lingkaran menjadi sesuatu yang lebih menarik). Sebagai penanda kita akan memiliki roket dengan lebar 48 dan panjang 24. Karena titik jangkar default penanda adalah sudut kiri atas, kita perlu mengimbanginya agar tepat di tengah penanda. Anda juga perlu mempertimbangkan hal ini saat melakukan rotasi, karena ini juga terjadi secara default di pojok kiri atas. Tampaknya kami sudah menyelesaikan perpindahan tersebut. Sekarang mari kita langsung ke rotasi, disinilah definisi garis singgung akan membantu kita, kita akan menentukan sudut menggunakan arctangen.

Fungsi TranslateAlong(path) yang mendefinisikan interpolator akan terlihat seperti ini:

Fungsi TranslateAlong(path) ( var l = path.getTotalLength(); var t0 = 0; return function(i) ( return function(t) ( var p0 = path.getPointAtLength(t0 * l);//poin sebelumnya var p = path.getPointAtLength(t * l);////titik saat ini var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle untuk tangen t0 = t ; //Pergeseran pusat ke pusat roket var centerX = p.x - 24, centerY = p.y - 12; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " 24" + " 12 "+")"; ) ) )
Implementasinya dapat dilihat di sini.