Dekomposisi Lingkaran SVG Ke Jalur
Diterbitkan: 2022-03-10Artikel ini dimulai dengan sebuah pengakuan: Saya suka kode tangan SVG. Tidak selalu demikian, tetapi cukup sering hal itu tampak aneh bagi orang-orang yang tidak memiliki kesukaan yang sama dengan saya. Ada banyak manfaat dari kemampuan menulis SVG dengan tangan, seperti mengoptimalkan SVG dengan cara yang tidak dapat dilakukan oleh alat (mengubah jalur menjadi jalur atau bentuk yang lebih sederhana), atau hanya dengan memahami cara kerja perpustakaan seperti D3 atau Greensock .
Dengan demikian, saya ingin melihat lebih dekat pada bentuk lingkaran di SVG dan hal-hal yang dapat kita lakukan dengannya ketika kita bergerak melewati lingkaran dasar. Mengapa lingkaran? Yah, aku suka lingkaran. Mereka adalah bentuk favorit saya.
Pertama (semoga Anda pernah melihat lingkaran dasar di SVG sebelumnya), inilah pena yang menunjukkannya:
Banyak hal yang dapat dilakukan dengan lingkaran: lingkaran dapat dianimasikan dan dapat diterapkan warna berbeda. Namun, ada dua hal yang sangat bagus yang tidak dapat Anda lakukan dengan lingkaran di SVG 1.1: Anda tidak dapat membuat elemen grafis lain bergerak di sepanjang jalur lingkaran (menggunakan elemen animateMotion
) dan Anda tidak dapat membentuk teks di sepanjang jalur lingkaran (ini akan hanya diperbolehkan setelah SVG 2.0 dirilis).
Mengubah Lingkaran Kita Menjadi Jalan
Ada alat online kecil yang dapat membantu Anda membuat jalur keluar dari lingkaran (Anda dapat mencobanya di sini), tetapi kami akan membuat semuanya dari awal sehingga kami dapat mengetahui apa yang sebenarnya terjadi di balik layar.
Untuk membuat jalur melingkar, sebenarnya kita akan membuat dua busur, yaitu setengah lingkaran yang melengkapi lingkaran dalam satu jalur. Seperti yang mungkin Anda perhatikan di SVG di atas, atribut CX
, CY
, dan R
masing-masing menentukan di mana lingkaran digambar di sepanjang sumbu X dan Y, sementara R
mendefinisikan jari-jari lingkaran. CX
dan CY
membuat pusat lingkaran, sehingga lingkaran digambar di sekitar titik itu.
Mereplikasi lingkaran itu bisa terlihat seperti ini:
<path d=" M (CX - R), CY a R,R 0 1,0 (R * 2),0 a R,R 0 1,0 -(R * 2),0 " />
Perhatikan bahwa CX
sama dengan atribut cx
dari lingkaran; hal yang sama berlaku untuk CY
dan atribut cy
dari lingkaran, serta R
dan atribut r
dari lingkaran. Karakter a
kecil digunakan untuk mendefinisikan segmen busur elips. Anda dapat menggunakan Z
opsional (atau z
) untuk menutup jalur.
Huruf kecil a
menunjukkan awal dari busur elips yang ditarik relatif ke posisi saat ini — atau dalam kasus khusus kami:
<path d=" M 25, 50 a 25,25 0 1,1 50,0 a 25,25 0 1,1 -50,0 " />
Anda dapat melihat keajaiban yang terjadi di pena ini:
Tersembunyi di bawah jalan adalah lingkaran dengan isian merah. Saat Anda bermain-main dengan nilai jalur, Anda akan melihat lingkaran itu selama jalur benar-benar menutupi lingkaran (jalur itu sendiri adalah lingkaran dengan ukuran yang sama), dan kita akan tahu bahwa kita melakukan hal yang benar .
Satu hal yang juga harus Anda ketahui adalah bahwa selama Anda menggambar busur relatif, Anda tidak perlu mengulangi perintah a
untuk setiap busur yang Anda gambar. Ketika 7 input pertama Anda selesai untuk arc Anda, 7 input kedua akan diambil untuk arc berikutnya.
Anda dapat mencoba ini dengan pena di atas dengan menghapus a
kedua di jalur:
a 25,25 0 1,1 50,0 25,25 0 1,1 -50,0
Ini mungkin terlihat sama, tetapi saya lebih memilih untuk membiarkannya sampai saya siap untuk menyelesaikan gambar, dan ini juga membantu saya untuk melacak di mana saya berada.
Bagaimana Jalan Ini Bekerja
Pertama, kita pindah ke koordinat X,Y
yang benar-benar diposisikan pada gambar. Itu tidak menggambar apa pun di sana — itu hanya bergerak di sana. Ingat bahwa untuk elemen lingkaran CX
, CY
menunjukkan pusat lingkaran; tetapi seperti yang terjadi pada busur elips, CX
dan CY
sebenarnya dari busur akan dihitung dari sifat-sifat lain dari busur tersebut.
Dengan kata lain, jika kita ingin CX
kita berada di 50
dan radius kita adalah 25
, maka kita perlu pindah ke 50 - 25
(tentu saja jika kita menggambar dari kiri ke kanan). Ini berarti bahwa busur pertama kita diambil dari 25 X, 50 Y
yang menghasilkan busur pertama kita menjadi 25,25 0 1,0 50,0
.
Mari kita urai apa arti sebenarnya dari nilai 25,25 0 1,0 50,0
dari busur kita:
-
25
: Jari-jari X relatif busur; -
25
: Jari-jari Y relatif dari busur; -
0 1,0
: Saya tidak akan berbicara tentang tiga nilai tengah (rotasi, bendera busur besar, dan properti bendera sapuan) karena mereka tidak terlalu penting dalam konteks contoh saat ini selama mereka adalah sama untuk kedua busur; -
50
: Koordinat X akhir (relatif) dari busur; -
0
: Koordinat Y akhir (relatif) dari busur.
Busur kedua adalah 25,25 0 1,0 -50,0
. Ingatlah bahwa busur ini akan mulai menggambar dari mana pun busur terakhir berhenti menggambar. Tentu saja, jari-jari X dan Y adalah sama ( 25
), tetapi koordinat akhir X adalah -50
dari koordinat sekarang.
Jelas sekali lingkaran ini bisa digambar dengan berbagai cara. Proses mengubah lingkaran menjadi jalur ini dikenal sebagai dekomposisi. Dalam spesifikasi SVG 2, dekomposisi lingkaran akan dilakukan dengan 4 busur, namun metode yang direkomendasikan belum memungkinkan untuk digunakan, karena saat ini bergantung pada fitur bernama jalur penutupan penyelesaian segmen yang belum ditentukan.
Untuk menunjukkan kepada Anda bahwa kita dapat menggambar lingkaran dengan banyak cara, saya telah menyiapkan pena kecil dengan berbagai contoh:
Jika Anda melihat lebih dekat, Anda akan melihat lingkaran asli kami bersama dengan lima contoh berbeda tentang cara menggambar jalur di atas lingkaran itu. Setiap jalur memiliki elemen desc
anak yang menjelaskan penggunaan nilai CX
, CY
dan R
untuk membangun lingkaran. Contoh pertama adalah yang kita bahas di sini sementara tiga lainnya menggunakan variasi yang harus dipahami dari membaca kode; contoh terakhir menggunakan empat busur setengah lingkaran alih-alih dua, agak mereplikasi proses yang dijelaskan dalam spesifikasi SVG 2 yang ditautkan di atas.
Lingkaran berlapis di atas satu sama lain menggunakan pengindeksan-z alami SVG untuk menempatkan elemen yang muncul belakangan di markup di atas elemen yang muncul lebih awal.
Jika Anda mengklik jalur melingkar di pena, klik pertama akan mencetak bagaimana jalur disusun ke konsol dan menambahkan kelas ke elemen sehingga Anda akan melihat warna goresan dari cara lingkaran digambar (Anda dapat melihat bahwa lingkaran pertama digambar dengan irisan awal dari goresan). Klik kedua akan menghapus lingkaran sehingga Anda memiliki kemampuan untuk berinteraksi dengan lingkaran di bawah ini.
Setiap lingkaran memiliki warna isian yang berbeda; elemen lingkaran yang sebenarnya berwarna kuning dan akan mengatakan "Anda mengklik lingkaran" ke konsol setiap kali diklik. Anda juga dapat, tentu saja, cukup membaca kode karena elemen desc
cukup mudah.
Pergi Dari Jalan Menuju Lingkaran
Saya kira Anda telah memperhatikan bahwa meskipun ada banyak cara berbeda untuk menggambar lingkaran, jalur yang digunakan masih terlihat sangat mirip. Seringkali — terutama dalam keluaran SVG dari program menggambar — lingkaran akan diwakili oleh jalur. Ini mungkin karena pengoptimalan kode program grafis; setelah Anda memiliki kode untuk menggambar jalur, Anda dapat menggambar apa saja, jadi gunakan saja. Ini dapat menyebabkan SVG agak membengkak yang sulit untuk dipikirkan.
Bacaan yang disarankan : “ Kiat Untuk Membuat Dan Mengekspor SVG yang Lebih Baik Untuk Web” oleh Sara Soueidan
Mari kita ambil SVG berikut dari Wikipedia sebagai contoh. Ketika Anda melihat kode untuk file itu, Anda akan melihat bahwa ia memiliki banyak editor cruft setelah Anda menjalankannya melalui SVGOMG Jake Archibald! (yang dapat Anda baca lebih lanjut di sini), Anda akan berakhir dengan sesuatu seperti file berikut yang telah cukup dioptimalkan tetapi lingkaran dalam dokumen masih dirender sebagai jalur:
Jadi, mari kita lihat apakah kita bisa mengetahui seperti apa seharusnya lingkaran itu jika itu adalah elemen lingkaran yang sebenarnya mengingat apa yang kita ketahui tentang cara kerja jalur. Jalur pertama dalam dokumen jelas bukan lingkaran sedangkan dua berikutnya adalah (hanya menunjukkan atribut d
):
M39 20a19 19 0 1 1-38 0 19 19 0 1 1 38 0z
M25 20a5 5 0 1 1-10 0 5 5 0 1 1 10 0z
Jadi mengingat bahwa a
kedua dapat ditinggalkan, mari kita tulis ulang ini agar lebih masuk akal. (Jalan pertama adalah lingkaran besar.)
M39 20 a19 19 0 1 1-38 0 a19 19 0 1 1 38 0z
Busur-busur itu kemudian jelas sebagai berikut:
aR R 0 1 1 - (R * 2) 0 aR R 0 1 1 (R * 2) 0
Ini berarti radius lingkaran kita adalah 19
, tetapi berapa nilai CX
dan CY
kita? Saya pikir M39
kami sebenarnya CX + R
, yang berarti bahwa CX
adalah 20
dan CY
adalah 20
juga.
Katakanlah Anda menambahkan lingkaran setelah semua jalur seperti ini:
<circle fill="none" stroke-width="1.99975" stroke="red" r="19" cx="20" cy="20" />
Anda akan melihat bahwa itu benar, dan bahwa lingkaran merah yang dicoret menutupi lingkaran besar itu. Jalur lingkaran kedua yang dirumuskan ulang terlihat seperti ini:
M25 20 a5 5 0 1 1-10 0 5 5 0 1 1 10 0z
Jelas, radiusnya adalah 5
, dan saya yakin nilai CX
dan CY
kita sama seperti sebelumnya: - 20
.
Catatan : Jika CX = 20
, maka CX + R = 25
. Lingkaran berada di dalam lingkaran yang lebih besar di tengah, jadi jelas itu harus memiliki nilai CX
dan CY
yang sama .
Tambahkan lingkaran berikut di akhir jalur:
<circle fill="yellow" r="5" cx="20" cy="20" />
Anda sekarang dapat melihat bahwa ini benar dengan melihat pena berikut:
Sekarang setelah kita mengetahui seperti apa seharusnya lingkaran itu, kita dapat menghapus jalur yang tidak diperlukan itu dan benar-benar membuat lingkaran — seperti yang dapat Anda lihat di sini:
Menggunakan Jalur Melingkar Kami Untuk Membungkus Teks
Jadi sekarang kita memiliki lingkaran di jalur, kita bisa membungkus teks di jalur itu. Di bawah ini adalah pena dengan jalur yang sama seperti pena "Semua Lingkaran" kami sebelumnya, tetapi dengan teks yang dibungkus di jalur tersebut. Setiap kali Anda mengklik jalur, jalur itu akan dihapus dan teks akan dibungkus di jalur yang tersedia berikutnya, seperti:
Melihat jalur yang berbeda, Anda akan melihat perbedaan kecil antara masing-masing (lebih lanjut tentang itu sedikit), tetapi pertama-tama ada sedikit ketidakcocokan lintas-browser yang terlihat — terutama terlihat di jalur pertama:
Pengembang Firefox | |
Chrome | |
Microsoft Edge |
Alasan mengapa "S" awal dari "Smashing" berada pada sudut yang lucu dalam solusi Firefox adalah karena di situlah kami benar-benar mulai menggambar jalur kami (karena perintah vR yang kami gunakan). Ini lebih jelas di versi Chrome di mana Anda dapat dengan jelas melihat irisan berbentuk pai pertama dari lingkaran yang kami gambar:
Chrome tidak mengikuti semua wedges, jadi ini adalah hasil ketika Anda mengubah teks menjadi "Smashing Magazine". |
Alasannya adalah Chrome memiliki bug terkait pewarisan atribut textLength
yang dideklarasikan pada elemen text
induk. Jika Anda ingin keduanya terlihat sama, letakkan atribut textLength
pada elemen textPath
serta teks. Mengapa? Karena ternyata Pengembang Firefox memiliki bug yang sama jika atribut textLength
tidak ditentukan pada elemen text
(ini telah terjadi selama beberapa tahun sekarang).
Microsoft Edge memiliki bug yang sama sekali berbeda; itu tidak bisa menangani spasi putih di antara Text
dan elemen TextPath
anak. Setelah Anda menghapus spasi, dan meletakkan atribut textLength
pada elemen text
dan textPath
, semuanya akan terlihat relatif sama (dengan sedikit variasi karena perbedaan font default dan sebagainya). Jadi, tiga bug berbeda di tiga browser berbeda — inilah mengapa orang sering lebih suka bekerja dengan perpustakaan!
Pena berikut menunjukkan bagaimana masalah dapat diperbaiki:
Saya juga telah menghapus berbagai warna isian karena memudahkan untuk melihat pembungkusan teks. Menghapus warna isian berarti bahwa fungsi kecil saya untuk memungkinkan Anda menelusuri jalur dan melihat tampilannya tidak akan berfungsi kecuali saya menambahkan atribut pointer-events="all"
, jadi saya telah menambahkannya juga.
Catatan : Anda dapat membaca lebih lanjut tentang alasannya di “Mengelola Interaksi SVG Dengan Properti Acara Pointer” yang dijelaskan oleh Tiffany B. Brown.
Kita sudah membahas pembungkus jalur multiarc, jadi sekarang mari kita lihat yang lain. Karena kita memiliki satu jalur yang sedang kita bungkus, teks akan selalu bergerak ke arah yang sama.
Gambar | Jalur | Penjelasan |
---|---|---|
M CX, CY a R, R 0 1,0 -(R * 2), 0 a R, R 0 1,0 R * 2, 0 dan menggunakan fungsi translate untuk memindahkan +R pada sumbu X. | Posisi awal untuk textPath kami (karena kami belum menentukannya dengan cara apa pun) ditentukan oleh busur akhir pertama kami -(R * 2) , dengan radius yang dimiliki busur itu sendiri. | |
M (CX + R), CY a R,R 0 1,0 -(R * 2),0 a R,R 0 1,0 (R * 2),0 | Hal yang sama berlaku seperti jalur sebelumnya. | |
M CX CY m -R, 0 a R,R 0 1,0 (R * 2),0 a R,R 0 1,0 -(R * 2),0 | Karena kita berakhir di (R * 2 ) di busur pertama kita, kita jelas akan mulai dari posisi yang berlawanan. Dengan kata lain, yang satu ini dimulai di mana dua jalur kita sebelumnya berakhir. | |
M (CX - R), CY a R,R 0 1, 1 (R * 2),0 a R,R 0 1, 1 -(R * 2),0 | Ini dimulai pada posisi yang sama dengan yang terakhir karena (R * 2) , tetapi ini berjalan searah jarum jam karena kami telah mengatur properti sapuan bendera (ditandai dengan warna kuning) ke 1 . |
Kami telah melihat cara membungkus teks pada satu jalur dalam lingkaran. Sekarang mari kita lihat bagaimana kita dapat memecah jalur itu menjadi dua jalur dan manfaat yang bisa Anda dapatkan darinya.
Mematahkan Jalan Kita Menjadi Beberapa Bagian
Ada banyak hal yang dapat Anda lakukan dengan teks di jalur Anda, yaitu mencapai efek gaya dengan elemen tspan
, menyetel offset teks, atau menganimasikan teks. Pada dasarnya, apa pun yang Anda lakukan akan dibatasi oleh jalur itu sendiri. Tetapi dengan memecah jalur multiarc kami menjadi jalur busur tunggal, kami dapat bermain-main dengan arah teks kami, pengindeksan z dari berbagai bagian teks kami, dan mencapai animasi yang lebih kompleks.
Pertama, kita akan ingin menggunakan gambar SVG lain untuk menunjukkan beberapa efek. Saya akan menggunakan berlian dari artikel tentang acara pointer yang saya sebutkan sebelumnya. Pertama, mari kita tunjukkan seperti apa tampilannya dengan teks melingkar jalur tunggal yang diletakkan di atasnya.
Mari kita asumsikan bahwa lingkaran kita adalah CX 295, CY 200, R 175
. Sekarang, mengikuti metode jalur melingkar, sekarang kita melihat yang berikut:
M (CX - R), CY a R,R 0 1,1 (R * 2),0 a R,R 0 1,1 -(R * 2),0
Saya tidak akan berbicara tentang jalur atau ukuran teks, warna isian atau goresan. Kita semua harus memahami itu sekarang, dan dapat membuatnya menjadi apa pun yang kita inginkan. Tetapi dengan melihat teksnya, kita dapat langsung melihat beberapa kelemahan atau keterbatasan:
- Semua teks berjalan dalam satu arah;
- Mungkin bagus untuk memiliki beberapa teks di belakang batu kecubung, terutama yang bertuliskan MAGAZINE. Untuk membuat garis 'M' dan 'E' pada lingkaran, 'A' harus berada di sisi titik bawah batu kecubung, yang terasa tidak seimbang dengan cara lain. (Saya merasa 'A' harus diposisikan dengan tepat dan mengarah ke bawah pada titik itu.)
Jika kita ingin memperbaiki masalah ini, kita perlu membagi jalur tunggal kita menjadi dua. Dalam pena berikut, saya telah memisahkan jalur menjadi dua jalur, (dan menempatkannya ke area defs
dari SVG untuk referensi textPath
kami):
Sekali lagi, dengan asumsi CX
kita adalah 295, CY 200, R 175
, maka kedua jalur tersebut dalam format berikut (untuk jalur setengah lingkaran teratas):
M (CX - R), CY a R,R 0 1,1 (R * 2),0
Dan berikut untuk bagian bawah:
M (CX + R), CY a R,R 0 1,1 -(R * 2),0
Namun, kami masih memiliki teks melingkar yang bergerak ke arah yang sama. Untuk memperbaikinya untuk semuanya kecuali Edge, yang harus Anda lakukan adalah menambahkan atribut side="right"
ke elemen text
yang menyimpan 'MAGAZINE' textPath
.
Membuat Teks Menuju Arah Lain
Jika kita ingin mendukung browser sebanyak yang kita bisa, kita harus mengubah jalur dan tidak bergantung pada atribut side
yang tidak sepenuhnya didukung. Yang dapat kita lakukan adalah menyalin jalur setengah lingkaran teratas kita, tetapi mengubah sapuan dari 1
menjadi 0
:
Sebelum:
M 120, 200 a 175,175 0 1,
M 120, 200 a 175,175 0 1,
1
350,0
350,0
Setelah:
M 120, 200 a 175,175 0 1,
M 120, 200 a 175,175 0 1,
0
350,0
350,0
Tapi teks kita sekarang digambar pada lingkaran dalam yang ditentukan oleh sapuan dan tidak akan terlihat bagus di browser yang berbeda. Ini berarti bahwa kita harus memindahkan posisi path kita untuk menyelaraskan dengan 'S' dari 'Smashing', membuat akhir X dari path lebih besar, dan mengatur beberapa offset ke teks. Seperti yang Anda lihat, ada juga sedikit perbedaan teks antara Firefox dan yang lainnya yang dapat kami tingkatkan dengan meningkatkan atribut textLength
pada elemen text
, serta menghapus spasi putih dari textPath
(karena Firefox jelas menganggap spasi putih bermakna).
Solusinya:
Ubah Z-Index Bagian Dari Teks Edaran Kami
Akhirnya, kami ingin membuat teks kami berjalan di depan dan di belakang batu kecubung. Nah, itu mudah. Ingat bahwa pengindeksan z elemen SVG didasarkan pada di mana mereka berada di markup? Jadi jika kita memiliki dua elemen, elemen 1
akan ditarik di belakang elemen 2
. Selanjutnya, yang harus kita lakukan adalah memindahkan elemen text
ke atas di markup SVG kita sehingga digambar sebelum batu kecubung.
Anda dapat melihat hasil di bawah ini di mana bagian dari kata 'MAGAZINE' disembunyikan oleh titik bawah batu kecubung.
Jika Anda melihat markup, Anda dapat melihat bahwa setengah lingkaran bawah teks telah dipindahkan ke sebelum jalur yang menarik batu kecubung.
Menganimasikan Bagian Lingkaran Kami
Jadi sekarang kita memiliki kemampuan untuk membuat teks melingkar dengan sepenuhnya mengontrol arah bagian dari teks kita dengan menempatkan teks menjadi dua setengah lingkaran. Ini tentu saja dapat juga dimanfaatkan untuk membuat animasi teks. Membuat animasi SVG lintas-browser benar-benar subjek artikel lain (atau lebih banyak artikel). Contoh-contoh ini hanya akan berfungsi di Chrome dan Firefox karena menggunakan sintaks animasi SMIL alih-alih keyframe CSS atau alat seperti Greensock. Tetapi ini memberikan indikator yang baik tentang efek yang dapat Anda capai dengan menganimasikan lingkaran yang terurai.
Ambil pena berikut:
Silakan tekan tombol 'Jalankan kembali' pada codepen untuk melihat animasi beraksi. Dua bagian dari teks melingkar kita mulai dianimasikan pada waktu yang sama, tetapi memiliki durasi yang berbeda sehingga berakhir pada waktu yang berbeda. Karena kami menganimasikan atribut textLength
, kami telah menempatkan dua arahan animate
di bawah setiap teks — satu untuk elemen text
(sehingga Firefox akan berfungsi) dan satu untuk elemen jalur textpath
(sehingga Chrome akan berfungsi).
Kesimpulan
Dalam artikel ini, kita telah melihat cara mengubah lingkaran menjadi jalur dan kembali lagi, untuk lebih memahami kapan kita perlu mengoptimalkan jalur dan kapan tidak. Kita telah melihat bagaimana mengubah lingkaran menjadi jalur membebaskan kita untuk menempatkan teks pada jalur melingkar, tetapi juga bagaimana membagi lebih jauh jalur melingkar menjadi setengah lingkaran dan mendapatkan kontrol yang lebih penuh atas arah dan animasi dari bagian-bagian komponen dari teks melingkar kita .
Bacaan Lebih Lanjut tentang SmashingMag:
- Memikirkan Kembali Responsif SVG
- Menganimasikan File SVG Dengan SVGator
- Menata Dan Menganimasikan SVG Dengan CSS
- Mengelola Interaksi SVG Dengan Properti Acara Pointer