Yollara SVG Daire Ayrıştırma
Yayınlanan: 2022-03-10Bu makale bir itirafla başlıyor: SVG'yi elle kodlamayı seviyorum. Her zaman böyle değil ama çoğu zaman benim tercihimi paylaşmayan insanlara tuhaf gelebilir. SVG'leri bir aracın yapamayacağı şekilde optimize etmek (bir yolu daha basit bir yol veya şekle dönüştürmek) veya basitçe D3 veya Greensock gibi kitaplıkların nasıl çalıştığını anlamak gibi SVG'yi elle yazabilmenin çok sayıda faydası vardır. .
Bununla birlikte, SVG'deki dairesel şekillere ve temel bir daireyi geçtiğimizde onlarla yapabileceğimiz şeylere daha yakından bakmak istiyorum. Neden daireler? Ben çevreleri severim. Onlar benim en sevdiğim şekil.
Öncelikle (umarız daha önce SVG'de basit bir daire görmüşsünüzdür), işte bunu gösteren bir kalem:
Bir daire ile pek çok şey yapılabilir: canlandırılabilir ve üzerine farklı renkler uygulanabilir. Yine de, SVG 1.1'de bir daireye yaptıramayacağınız çok güzel iki şey vardır: Dairenin yolu boyunca başka bir grafik öğeyi hareket ettiremezsiniz ( animateMotion
öğesini kullanarak) ve bir dairenin yolu boyunca bir metni şekillendiremezsiniz (bu, yalnızca SVG 2.0 yayınlandıktan sonra izin verilir).
Çevremizi Bir Yola Dönüştürmek
Çevrelerden yollar oluşturmanıza yardımcı olabilecek küçük bir çevrimiçi araç var (burada deneyebilirsiniz), ancak sahne arkasında gerçekte neler olduğunu öğrenebilmemiz için her şeyi sıfırdan oluşturacağız.
Dairesel bir yol yapmak için, aslında iki yay yapacağız, yani daireyi tek bir yolda tamamlayan yarım daireler. Muhtemelen yukarıdaki SVG'de fark ettiğiniz gibi, CX
, CY
ve R
nitelikleri sırasıyla dairenin X ve Y ekseni boyunca nerede çizileceğini tanımlarken, R
dairenin yarıçapını tanımlar. CX
ve CY
dairenin merkezini oluşturur, böylece daire o noktanın etrafında çizilir.
Bu daireyi kopyalamak şöyle görünebilir:
<path d=" M (CX - R), CY a R,R 0 1,0 (R * 2),0 a R,R 0 1,0 -(R * 2),0 " />
cx
CX
ile aynı olduğuna dikkat edin; aynı şey çemberin CY
ve cy
niteliği ile çemberin R
ve r
niteliği için de geçerlidir. Küçük a
karakteri, eliptik bir yayın segmentini tanımlamak için kullanılır. Yolu kapatmak için isteğe bağlı bir Z
(veya z
) kullanabilirsiniz.
Küçük harf a
, mevcut konuma göre çizilen eliptik bir yayın başlangıcını belirtir - veya bizim özel durumumuzda:
<path d=" M 25, 50 a 25,25 0 1,1 50,0 a 25,25 0 1,1 -50,0 " />
Bu kalemde gerçekleşen sihri görebilirsiniz:
Yolun altında kırmızı dolgulu bir daire gizlidir. Yolun değerleriyle oynadıkça, yol daireyi tamamen kapsadığı sürece (yolun kendisi aynı boyutta bir dairedir) o daireyi göreceksiniz ve işleri doğru yaptığımızı bileceğiz. .
Ayrıca bilmeniz gereken bir şey de, göreceli yaylar çizdiğiniz sürece, çizdiğiniz her yay için a
komutunu tekrarlamanıza gerek olmadığıdır. Arkınız için ilk 7 girişiniz yapıldığında, sonraki 7 girişiniz bir sonraki ark için alınacaktır.
Bunu, yoldaki ikinci a
kaldırarak yukarıdaki kalemle deneyebilirsiniz:
a 25,25 0 1,1 50,0 25,25 0 1,1 -50,0
Bu aynı görünebilir, ancak bir çizimi bitirmeye hazır olana kadar bırakmayı tercih ederim ve bu da nerede olduğumu takip etmeme yardımcı olur.
Bu Yol Nasıl Çalışır?
İlk olarak, görüntüde kesinlikle konumlandırılmış bir X,Y
koordinatına geçiyoruz. Oraya hiçbir şey çizmez - sadece orada hareket eder. Bir daire elemanı için CX
, CY
dairenin merkezini gösterdiğini unutmayın; ancak eliptik yayda olduğu gibi, yayın gerçek CX
ve CY
o yayın diğer özelliklerinden hesaplanacaktır.
Başka bir deyişle, CX
50
ve yarıçapımızın 25
olmasını istiyorsak, o zaman 50 - 25
gitmemiz gerekir (tabii soldan sağa çekiyorsak). Bu, ilk yayımızın 25 X, 50 Y
çizildiği anlamına gelir, bu da ilk 25,25 0 1,0 50,0
olmasını sağlar.
25,25 0 1,0 50,0
değerinin gerçekte ne anlama geldiğini çözelim:
-
25
: Yayın göreli X yarıçapı; -
25
: Yayın göreli Y yarıçapı; -
0 1,0
: Ortadaki üç değerden (rotasyon, büyük-yay-flag ve süpürme-flag özellikleri) bahsetmeyeceğim çünkü bunlar mevcut örnek bağlamında çok önemli değiller. her iki yay için de aynıdır; -
50
: Yayın bitiş X koordinatı (göreli); -
0
: Yayın bitiş Y koordinatı (göreli).
İkinci yay 25,25 0 1,0 -50,0
. Bu yayın, son yayın çizimi durdurduğu yerden çizime başlayacağını unutmayın. Tabii ki, X ve Y yarıçapı aynıdır ( 25
), ancak bitiş X koordinatı, mevcut olanın -50
.
Açıkçası bu daire birçok farklı şekilde çizilebilirdi. Bir daireyi bir yola çevirme işlemi, ayrıştırma olarak bilinir. SVG 2 spesifikasyonunda bir dairenin ayrıştırılması 4 yay ile yapılacaktır, ancak önerdiği yöntemin kullanılması henüz mümkün değildir, çünkü şu anda henüz belirtilmemiş olan segment tamamlama yakın yol adlı bir özelliğe bağlıdır.
Çemberi birçok şekilde çizebileceğimizi göstermek için çeşitli örneklerle küçük bir kalem hazırladım:
Daha yakından bakarsanız, orijinal dairemizi ve bu dairenin üzerine nasıl yollar çizileceğine dair beş farklı örnek göreceksiniz. Her yolun, daireyi oluşturmak için CX
, CY
ve R
değerlerinin kullanımını açıklayan bir alt desc
öğesi vardır. İlk örnek burada tartıştığımız örnektir, diğer üç örnek ise kodu okuyarak anlaşılması gereken varyasyonları kullanır; son örnekler, yukarıda bağlantılı SVG 2 spesifikasyonunda açıklanan işlemi bir şekilde kopyalayarak, iki yerine dört yarım daire biçimli yay kullanır.
Daireler, SVG'nin işaretlemede daha sonra gelen öğeleri daha önce gelenlerin üzerine yerleştirmeye yönelik doğal z-endeksini kullanarak üst üste katmanlanmıştır.
Kalemdeki dairesel yollara tıklarsanız, ilk tıklama yolun konsola nasıl yapılandırıldığını yazdırır ve öğeye bir sınıf ekler, böylece dairenin nasıl çizildiğinin kontur rengini görürsünüz (bkz. ilk dairenin vuruştan bir başlangıç kaması ile çizilmesi). İkinci tıklama, daireyi kaldıracak, böylece aşağıdaki daireyle etkileşim kurma olanağına sahip olacaksınız.
Her dairenin farklı bir dolgu rengi vardır; asıl daire öğesi sarıdır ve her tıklandığında konsola “Çembere tıkladınız” diyecektir. Ayrıca, elbette, desc
öğeleri oldukça basit olduğu için kodu basitçe okuyabilirsiniz.
Bir Yoldan Bir Çembere Gitmek
Çemberi çizmenin birçok farklı yolu olsa da, kullanılan yolların hala oldukça benzer göründüğünü fark etmişsinizdir. Genellikle - özellikle bir çizim programından SVG çıktılarında - daireler yollarla temsil edilir. Bu muhtemelen grafik program kodunun optimizasyonundan kaynaklanmaktadır; Bir yol çizecek koda sahip olduğunuzda her şeyi çizebilirsiniz, o yüzden onu kullanın. Bu, akıl yürütmesi zor olan biraz şişirilmiş SVG'lere yol açabilir.
Önerilen okuma : Sara Soueidan'ın "Web İçin Daha İyi SVG'ler Oluşturma ve Dışa Aktarma İpuçları"
Örnek olarak Wikipedia'dan aşağıdaki SVG'yi alalım. Bu dosyanın koduna baktığınızda, Jake Archibald'ın SVGOMG'sinde çalıştırdıktan sonra çok fazla editör hatası olduğunu göreceksiniz! (bunun hakkında daha fazlasını buradan okuyabilirsiniz), aşağıdaki gibi oldukça optimize edilmiş bir dosyaya sahip olacaksınız, ancak belgedeki daireler hala yol olarak işleniyor:
Öyleyse, yolların nasıl çalıştığı hakkında bildiklerimizi göz önünde bulundurarak, bu çemberlerin gerçek çember öğeleri olsaydı ne olması gerektiğini bulabilecek miyiz bir bakalım. Belgedeki ilk yol açıkça bir daire değil, sonraki ikisi ise (sadece d
niteliğini gösteriyor):
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
İkinci a
atlanabileceğini hatırlayarak, biraz daha anlamlı olması için bunları yeniden yazalım. (İlk yol büyük dairedir.)
M39 20 a19 19 0 1 1-38 0 a19 19 0 1 1 38 0z
Bu yaylar daha sonra açıkça aşağıdaki gibidir:
aR R 0 1 1 - (R * 2) 0 aR R 0 1 1 (R * 2) 0
Bu, daire yarıçapımızın 19
olduğu anlamına gelir, ancak CX
ve CY
değerlerimiz nelerdir? M39
aslında CX
CX + R
olduğunu düşünüyorum, bu da CX'in 20
ve CY
de 20
olduğu anlamına gelir.
Diyelim ki bunun gibi tüm yollardan sonra bir daire eklediniz:
<circle fill="none" stroke-width="1.99975" stroke="red" r="19" cx="20" cy="20" />
Bunun doğru olduğunu ve kırmızı çizgili dairenin tam olarak büyük daireyi kapladığını göreceksiniz. Yeniden formüle edilen ikinci daire yolu şöyle görünür:
M25 20 a5 5 0 1 1-10 0 5 5 0 1 1 10 0z
Açıkça, yarıçap 5
ve bahse girerim CX
ve CY
değerlerimiz öncekiyle aynıdır: - 20
.
Not : CX = 20
ise , CX + R = 25
. Daire, merkezdeki daha büyük olanın içinde oturuyor, bu yüzden açıkçası aynı CX
ve CY
değerlerine sahip olması gerekiyor.
Yolların sonuna aşağıdaki daireyi ekleyin:
<circle fill="yellow" r="5" cx="20" cy="20" />
Şimdi aşağıdaki kaleme bakarak bunun doğru olduğunu görebilirsiniz:
Artık dairelerin ne olması gerektiğini bildiğimize göre, bu gereksiz yolları kaldırabilir ve aslında burada görebileceğiniz gibi daireleri oluşturabiliriz:
Metni Sarmak İçin Dairesel Yolumuzu Kullanma
Artık yollarda dairelerimiz olduğuna göre, bu yollara metin sarabiliriz. Aşağıda, önceki "Tüm Çemberler" kalemimizle aynı yollara sahip, ancak yolun üzerine metin sarılmış bir kalem bulunmaktadır. Bir yola her tıkladığınızda, o yol silinecek ve metin aşağıdaki gibi bir sonraki uygun yola sarılacaktır:
Farklı yollara baktığınızda, her biri arasında küçük farklılıklar göreceksiniz (birazdan daha fazlası), ancak önce görülmesi gereken küçük bir tarayıcılar arası uyumsuzluk var - özellikle ilk yolda fark edilir:
Firefox Geliştiricisi | |
Krom | |
Microsoft Kenarı |
Firefox çözümünde “Smashing” in başlangıç “S” sinin bu komik açıda oturmasının nedeni, aslında yolumuzu çizmeye başladığımız yer (kullandığımız vR komutu nedeniyle). Bu, dairemizin çizdiğimiz ilk pasta şeklindeki kamasını açıkça görebileceğiniz Chrome sürümünde daha belirgindir:
Chrome tüm takozları takip etmez, bu nedenle metni "Smashing Magazine" olarak değiştirdiğinizde ortaya çıkan sonuç budur. |
Bunun nedeni, Chrome'un üst text
öğesinde bildirilen textLength
niteliğinin devralınmasıyla ilgili bir hatası olmasıdır. Her ikisinin de aynı görünmesini istiyorsanız, textLength
niteliğini metnin yanı sıra textPath
öğesine de koyun. Niye ya? Çünkü, text
öğesinde textLength
niteliği belirtilmemişse, Firefox Developer'ın aynı hataya sahip olduğu ortaya çıktı (bu, birkaç yıldır böyledir).
Microsoft Edge'in tamamen farklı bir hatası var; Text
ve alt TextPath
öğesi arasındaki boşlukları işleyemez. Boşluğu kaldırdıktan ve hem text
hem de textPath
öğelerine textLength
niteliğini yerleştirdikten sonra, hepsi nispeten aynı görünecektir (varsayılan yazı tiplerindeki farklılıklar vb. nedeniyle küçük farklılıklarla). Yani, üç farklı tarayıcıda üç farklı hata — bu yüzden insanlar genellikle kütüphanelerle çalışmayı tercih ediyor!
Aşağıdaki kalem, sorunların nasıl çözülebileceğini gösterir:
Metin kaydırmayı görmeyi kolaylaştırdığı için çeşitli dolgu renklerini de kaldırdım. Dolgu renklerini kaldırmak, yollar arasında dolaşmanıza ve nasıl göründüklerini görmenize izin veren küçük işlevimin, bir pointer-events="all"
özniteliği eklemedikçe işe yaramayacağı anlamına gelir, bu yüzden onları da ekledim.
Not : Bunun nedenleri hakkında daha fazla bilgiyi Tiffany B. Brown tarafından açıklanan “İşaretçi Olayları Özelliğiyle SVG Etkileşimini Yönetme” bölümünde okuyabilirsiniz.
Çoklu yay yolunun sarılmasını zaten tartıştık, o yüzden şimdi diğerlerine bakalım. Sardığımız bir yolumuz olduğundan, metin her zaman aynı yönde hareket edecektir.
resim | Yol | Açıklama |
---|---|---|
M CX, CY a R, R 0 1,0 -(R * 2), 0 a R, R 0 1,0 R * 2, 0 ve +R X ekseninde hareket ettirmek için translate işlevini kullanır. | textPath başlangıç konumu (çünkü hiçbir şekilde belirtmedik), yayın sahip olduğu yarıçap göz önüne alındığında, ilk bitiş arkımız -(R * 2) tarafından belirlenir. | |
M (CX + R), CY a R,R 0 1,0 -(R * 2),0 a R,R 0 1,0 (R * 2),0 | Aynı önceki yol için de geçerlidir. | |
M CX CY m -R, 0 a R,R 0 1,0 (R * 2),0 a R,R 0 1,0 -(R * 2),0 | İlk yayında (R * 2 ) ile bittiğimiz için, açıkçası ters pozisyonda başlayacağız. Başka bir deyişle, bu, önceki iki yolumuzun bittiği yerden başlıyor. | |
M (CX - R), CY a R,R 0 1, 1 (R * 2),0 a R,R 0 1, 1 -(R * 2),0 | Bu, (R * 2) nedeniyle sonuncusu ile aynı konumda başlar, ancak süpürme bayrağı özelliğini (sarı ile işaretlenmiş) 1 olarak ayarladığımız için saat yönünde çalışır. |
Metni bir daire içinde tek bir yola nasıl kaydıracağımızı gördük. Şimdi bu yolu nasıl iki yola ayırabileceğimize ve bundan elde edebileceğiniz faydalara bir göz atalım.
Yollarımızı Parçalara Ayırmak
Yolunuzdaki metinle yapabileceğiniz pek çok şey vardır, yani tspan
öğeleriyle stilistik efektler elde etmek, metnin ofsetini ayarlamak veya metni canlandırmak. Temel olarak, ne yaparsanız yapın yolun kendisi tarafından kısıtlanacaktır. Ancak çok yaylı yollarımızı tek yaylı yollara bölerek, metnimizin yönü, metnimizin farklı bölümlerinin z-indekslemesi ile oynayabilir ve daha karmaşık animasyonlar elde edebiliriz.
İlk olarak, bazı efektleri göstermek için başka bir SVG görüntüsü kullanmak isteyeceğiz. Daha önce bahsettiğim pointer olaylarıyla ilgili makaledeki elması kullanacağım. İlk olarak, üzerine tek bir yol dairesel metin serilerek nasıl görüneceğini gösterelim.
CX 295, CY 200, R 175
olduğunu varsayalım. Şimdi, Dairesel yol yöntemini izleyerek aşağıdakileri görüyoruz:
M (CX - R), CY a R,R 0 1,1 (R * 2),0 a R,R 0 1,1 -(R * 2),0
Yol veya metin boyutu, dolgu veya kontur rengi hakkında konuşmayacağım. Hepimiz bunu şimdiye kadar anlamalı ve istediğimiz gibi olmasını sağlayabilmeliyiz. Ancak metne bakarak, bazı olumsuzlukları veya sınırlamaları hemen görebiliriz:
- Metin tek yönde çalışır;
- Metnin bir kısmının ametistin arkasına geçmesi güzel olabilir, özellikle MAGAZINE yazdığı yerde. Çember üzerinde 'M' ve 'E' çizgisini oluşturabilmek için, 'A'nın ametistin yan alt noktasında olması gerekir, bu da başka bir şekilde dengesiz hissettirir. ('A'nın tam olarak konumlandırılması ve bu noktada aşağıyı göstermesi gerektiğini düşünüyorum.)
Bu sorunları düzeltmek istiyorsak, tek yolumuzu ikiye bölmemiz gerekiyor. Aşağıdaki kalemde yolu iki yola ayırdım (ve bunları textPath
s'nin başvurması için SVG'nin defs
alanına yerleştirdim):
Yine, CX
295, CY 200, R 175
olduğunu varsayarsak, o zaman iki yol aşağıdaki formattadır (en üstteki yarım daire yolu için):
M (CX - R), CY a R,R 0 1,1 (R * 2),0
Ve alt için aşağıdakiler:
M (CX + R), CY a R,R 0 1,1 -(R * 2),0
Ancak yine de hepsi aynı yönde hareket eden dairesel metinlerimiz var. Bunu Edge dışındaki her şey için düzeltmek için tek yapmanız gereken, 'DERGİ' textPath
tutan text
öğesine side="right"
niteliğini eklemektir.
Metnin Başka Bir Yöne Gitmesini Sağlamak
Mümkün olduğu kadar çok tarayıcıyı desteklemek istiyorsak, yolu değiştirmeli ve tam olarak desteklenmeyen side
özniteliğe güvenmemeliyiz. Yapabileceğimiz şey, en üstteki yarım daire yolumuzu kopyalamak, ancak taramayı 1
0
değiştirmek:
Önce:
M 120, 200 a 175,175 0 1,
M 120, 200 a 175,175 0 1,
1
350,0
350,0
Sonrasında:
M 120, 200 a 175,175 0 1,
M 120, 200 a 175,175 0 1,
0
350,0
350,0
Ancak metnimiz artık tarama tarafından tanımlanan iç daireye çiziliyor ve farklı tarayıcılarda pek hoş görünmeyecek. Bu, 'Smashing'in 'S'si ile hizalanmak için yolumuzun konumunu hareket ettirmemiz, yolun sonunu X'i büyütmemiz ve metne bir miktar ofset ayarlamamız gerektiği anlamına gelir. Gördüğünüz gibi, Firefox ile diğerleri arasında text
öğesindeki textLength
niteliğini artırarak ve ayrıca textPath
boşlukları kaldırarak geliştirebileceğimiz küçük bir metin farkı da var (çünkü Firefox açıkça boşlukların anlamlı olduğunu düşünüyor).
Çözüm:
Genelge Metnimizin Bir Kısmının Z-İndeksini Değiştirin
Son olarak, metnimizin ametistin hem önüne hem arkasına geçmesini istiyoruz. Bu kolay. SVG'nin z-endeksleme elemanının işaretlemede bulundukları yere göre olduğunu hatırlıyor musunuz? Yani iki elementimiz varsa, element 1
, element 2
arkasına çizilecektir. Ardından, tek yapmamız gereken, SVG işaretlememizde bir text
öğesini ametistten önce çizilmesi için yukarı taşımaktır.
Aşağıda 'DERGİ' kelimesinin hangi kısımlarının ametistin alt noktası tarafından gizlendiğini görebilirsiniz.
İşaretlemeye bakarsanız, metnin alt yarım dairesinin ametisti çizen yoldan önce hareket ettirildiğini görebilirsiniz.
Çemberimizin Parçalarını Canlandırma
Yani şimdi metni iki yarım daireye koyarak metnimizin bölümlerinin yönlülüğünü tamamen kontrol ederek dairesel metin yapma yeteneğine sahibiz. Bu, elbette, metnin animasyonlarını yapmak için de kullanılabilir. Tarayıcılar arası SVG animasyonları yapmak gerçekten başka bir makalenin (veya daha birçok makalenin) konusudur. Bu örnekler, CSS ana kareleri veya Greensock gibi araçlar yerine SMIL animasyonları sözdizimi kullanıldığından yalnızca Chrome ve Firefox'ta çalışacaktır. Ancak, ayrıştırılmış daireyi canlandırarak elde edebileceğiniz etkilerin iyi bir göstergesidir.
Aşağıdaki kalemi alın:
Animasyonu çalışırken görmek için lütfen kod kalemindeki 'Yeniden Çalıştır' düğmesine basın. Dairesel metnimizin iki bölümü aynı anda canlandırılmaya başlar, ancak farklı sürelere sahip oldukları için farklı zamanlarda biterler. textLength
niteliğini canlandırdığımız için, her metnin altına iki animate
yönergesi koyduk - biri text
öğesi için (böylece Firefox çalışacaktır) ve diğeri metin textpath
öğesi için (böylece Chrome çalışacaktır).
Çözüm
Bu makalede, bir yolu ne zaman optimize etmemiz gerektiğini ve ne zaman optimize etmemiz gerekmediğini daha iyi anlamak için bir daireyi bir yola nasıl çevireceğimizi ve tekrar geri döneceğimizi gördük. Daireyi bir yola çevirmenin, metni dairesel yola yerleştirmek için bizi nasıl özgürleştirdiğini, aynı zamanda dairesel yolu yarım dairelere nasıl daha fazla böleceğimizi ve dairesel metnimizin bileşen parçalarının yönlülüğü ve animasyonu üzerinde nasıl daha fazla kontrol sahibi olacağımızı gördük. .
SmashingMag'de Daha Fazla Okuma :
- Duyarlı SVG'yi Yeniden Düşünmek
- SVGator ile SVG Dosyalarını Canlandırma
- CSS ile SVG'leri Şekillendirme ve Canlandırma
- İşaretçi Olayları Özelliğiyle SVG Etkileşimini Yönetme