SVG Metin Eğitimi: Web'de Metin Açıklaması
Yayınlanan: 2022-03-11HTML5 ve CSS3 ile web tarayıcıları bir dizi harika teknoloji elde etti: 3D grafikler, yuvalar, diziler ve daha fazlası. Bunlarla, web uygulamaları, kullanıldıkları bilgisayarların ve işletim sistemlerinin en gelişmiş özelliklerinden bazılarından yararlanabilir. Web tarayıcısı, uygulama geliştirme için, onsuz yaşayamayacağımız çok sayıda güçlü web uygulamasının son zamanlardaki yükselişinden açıkça anlaşılacağı gibi, sağlam ve çok yönlü bir ekosistem sunar. Ancak, hala eksik olan bir şey, HTML metin açıklamalarının ve dekorasyonunun güzelliğidir. Metin dekorasyonu nedir? Dalgalı alt çizgiler, sağlam vurgular ve dalgalı üst üste çizgiler, web tarayıcılarının yerel destek sağlamadığı şeylerden bazılarıdır. Bu kulağa yararlı olmaktan çok ayrıntılı gelebilir, ancak JavaScript Geliştiricilerinin bu stilleri üretme yeteneği, e-öğrenme kaynakları ve web tabanlı e-kitap okuyucular gibi konularda yararlı olabilir. Ayrıca bu, doğal tasarım ilkeleri etrafında dönen web uygulamalarında kullanıcı deneyiminin geliştirilmesine katkıda bulunabilir. En azından, böyle bir araç oluşturmak eğlencelidir ve bir web tarayıcısının birçok tuhaflığı hakkında fikir verir.
Geliştiriciler, web tarayıcı sınırlaması için birçok geçici çözüm buldu. Bazıları görüntüleri "::after" sözde öğelerinde kullandığından, bu geçici çözümlerin çoğu CSS'nin daha az sezgisel yollarla kullanılmasını içerir. Bu işe yarar, ancak her stil-renk çifti için birçok görüntü elde etmek genellikle zor olur. Bu makale, bu sorunu zarif bir şekilde çözmeye çalışan bir JavaScript kitaplığının anatomisine bir göz atmaktadır.
Kitaplık açık kaynak kodludur ve GitHub: Text Annotator'da mevcuttur.
genel bakış
Bu kitaplık geliştirilirken, en popüler web tarayıcılarıyla (IE 9+ dahil) uyumluluğun sağlanmasına özel önem verildi. Ancak, çoğu kişinin bu sorunu nasıl çözdüğünün aksine, kitaplık özellikle belirsiz CSS hilelerine dayanmaz; veya daha kötüsü, özel Unicode sembolleri. Bunun yerine çok daha iyi, daha temiz metin süslemeleri elde etmek için SVG'yi kullanır.
Temel olarak kitaplık, DIV öğelerini otomatik olarak oluşturmak, bunları açıklama eklenecek metinlerin altına yerleştirmek ve arka planlarını SVG görüntüleri ile doldurmak için kullanılabilen bir Annotator "sınıfı" uygular. Dekorasyonları daha da özelleştirmek için birden fazla DIV birleştirilebilir. Yaklaşım, tarayıcılar arası uyumludur, dekoratif öğelerin konumlandırılması konusunda esneklik sağlar ve özel şablonlarla daha kolay genişletmeye olanak tanır.
Kitaplık, herhangi bir ek bağımlılık olmaksızın kompakt ve hızlı JavaScript kodu üretmeye yardımcı olan modüler ve çapraz tarayıcı olduğu için Google Kapatma Araçları kullanılarak geliştirilmiştir.
Mimari
Kitaplık, bir JavaScript "sınıfları" koleksiyonu olarak tasarlanmıştır ve gerekli tüm işlevleri "sınıf" Annotator aracılığıyla kullanıcıya sunar:
Kullanılabilir işlevlerin kısa bir özeti:
annotateDocument - "data-annotate" özniteliği ile işaretlenmiş öğelere açıklama ekler.
altı çizili - öğenin altını çizer
vurgula - öğeyi vurgular
grev - grev öğesi
underlineSelected - seçili metnin altını çizer
HighlightSelected - seçili metni vurgular
StrikeSelected - seçili metne vurur
unannotateElement - öğeden açıklamayı kaldırır
getTemplates - açıklama şablonlarının sözlüğünü döndürür
setUnderlineOptions - altı çizili açıklayıcı için ayarları ayarlar
setHighlightOptions - vurgu açıklayıcı için ayarları ayarlar
setStrikeOptions - vuruş açıklayıcısı için ayarları belirler
Annotator sınıfı, her açıklama işlevi için AnnotatorImpl sınıfının üç örneğini tutar: altını çiz, vurgula ve vur.
tvs.Annotator = function() { this.underliner_ = new tvs.AnnotatorImpl( 'underliner', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.underlinePositioner); this.highlighter_ = new tvs.AnnotatorImpl( 'highlighter', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.highlightPositioner, {opacity: 0.45}); this.striker_ = new tvs.AnnotatorImpl( 'striker', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.strikePositioner); };
AnnotatorImpl örnekleri, farklı kimlikler ve konumlandırıcı yardımcı nesnelerle oluşturulur. Geçilen kimlikler daha sonra CSS sınıf adlarında ve dahili alan adlarında kullanılır ve kimliklerin benzersiz olmasını gerektirir. Ayrıca, bilinen şablonların listesine bir başvuru iletilir (daha sonra değiştirilebilir).
Her konumlayıcı nesnesi, yalnızca "getPosition" yöntemine sahip olan ve aşağıdaki gibi görünen bir IPositioner arabirimi uygulamasıdır:
/** * Underline positioner * @implements {tvs.IPositioner} */ tvs.AnnotatorCore.underlinePositioner = /** @type {!tvs.IPositioner} */ ({ /** * @param {Object} elementRect * @param {number} annotationHeight * @return {{left: number, top: number, width: number, height: number}} */ getPosition: function(elementRect, annotationHeight) { return { width: elementRect.width, height: annotationHeight, left: elementRect.left, top: elementRect.bottom - (elementRect.height * 0.1) }; } });
Bu, her şablonun altı çizili, vurgulu veya üstü çizili metin açıklamalarıyla kullanılmasına olanak tanır. Bir öğeye açıklama uygulandığında, öğenin sınırlayıcı kutusu, aşağıda gösterildiği gibi "getElementRects" çağrılarak elde edilir:
var rects = elemOrEv.getClientRects();
Bu yöntem, bir istemcideki her kutu için sınırlayıcı dikdörtgenleri gösteren bir dikdörtgen koleksiyonu döndürür. Her rektasyonu beton konumlandırıcıya geçtikten sonra hedef sınırları alacağız.
SVG Metin Açıklama Şablonları
Daha önce de belirtildiği gibi, her türlü SVG metin açıklamaları için kullanılan tek bir şablon seti vardır. Her şablon, şablon bölümlerinden oluşur. Bir şablon parçası, parçanın içeriğini, şablon genişliğini ve çizim modunu temsil eden bir varlıktır.
İçerik
İçerik, bir dize olarak temsil edilen bir dizi SVG öğesidir. Bu içerik, görünümün genişliğinin ve yüksekliğinin (piksel olarak) ayarlandığı bir kök SVG düğümüne sahip olmadığından, şablonun parça oluşturucusu bunları parametre olarak kabul eder. Örneğin, bir görünümün boyutunu 100px x 100px olarak belirleyebilir ve (50, 50) ve (25, 25)'e bir çizgi çizebilirsiniz. Açıklama uygulandıktan sonra, tüm svg öğeleri istenen boyuta uygun şekilde boyutlandırılacaktır. İçerik değeri, kullanıcı tarafından seçilen renkle değiştirilecek olan “{0}” dizesini kullanabilir.
Aşağıdaki SVG, çapraz bir çizgi oluşturur. Bunu, kısaca aşağıdaki örnek açıklama stilinde parçalardan biri olarak kullanacağız:
<line x1="0" y1="0" x2="5" y2="5" stroke-width="2" stroke="red" />
Genişlik
Şablon genişliği, "*", "yükseklik" veya başka herhangi bir şey olabilen bir dizedir:
“*”, birbirine eşit bir yıldızla tüm öğelerin genişliğini ayarlar
"yükseklik", ek açıklama öğesinin yüksekliğine eşit genişliği ayarlar
Burada ayarlanan diğer her şey doğrudan CSS genişliği ve minimum genişlik özelliklerine ayarlanacaktır.
Çizim Modu
Çizim modu, "tekrar" veya "uzatma" olabilen bir dizedir. Değerlerin gösterdiği gibi, "tekrar" olarak ayarlamak içeriği tekrar edecek, "uzat" olarak ayarlamak ise içeriği uzatacaktır.
Bu üç parametreyi yapılandırarak neler başarabileceğimize bir örnek:
Yukarıdaki örnekteki metin açıklaması 4 bölümden oluşmaktadır. İlk kısım, şablon genişliğinin "yüksekliğe" ve çizim modunun "tekrar"a ayarlandığı çapraz çizgidir. İkinci bölümün şablon genişliği “*” ve çizim modu “tekrar” olarak ayarlanmıştır. Üçüncü kısım “15 piksel” genişliğinde ve “tekrar” modunda çizilecek şekilde ayarlanmıştır. Son olarak, son parçanın genişliği “*” ve çizim modu “streç” olarak ayarlanmıştır.
Bu genişlikler değerlendirildiğinde, ilk kısım 5 piksel (annotation elemanının yüksekliğine eşit), üçüncü kısım 15 piksel (set olarak) alır ve kalan boşluk ikinci ve dördüncü kısımlar arasında eşit olarak bölünür.
Aynı şablon kullanılarak aynı metin parçası vurgulandığında, şunu elde ederiz:
Anlayabileceğiniz gibi, açıklama öğesinin yüksekliği ve ilk parçanın genişliği daha fazladır (çünkü o parçanın şablon genişliği “yükseklik” olarak ayarlanmıştır). Doğal olarak, üçüncü parçanın genişliği önceki örneğe göre değişmeden kaldı.
Aynı şablona sahip aynı metne üstü çizili efekt uygulamak, birincisine çok benzer bir sonuç verir. Tek fark, açıklama öğelerinin konumlandığı konumdur:
Bu metin açıklamaları karmaşık görünse de (görünüşleri dört farklı parçaya sahiptir), hepsi çok basit SVG öğeleri kullanır. Ek bir örnek olarak, dalgalı bir çizgi yapmak için aşağıdaki basit SVG içeriğine sahip tek bir parça gerekir:
var t = new tvs.Template(new tvs.SvgTemplatePart( '<line y2="16.00" x2="20" y1="4.00" ' + 'x1="10" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>' + '<line y2="4.00" x2="10" y1="16.00" ' + 'x1="0" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>', 20, 20, 'repeat' ))
Bu şablonlar değerlendirildiğinde içerik yeniden boyutlandırılır ve “{0}” otomatik olarak belirtilen renkle değiştirilir. Dahası, yeni şablonlar eklemek, onları bir JavaScript nesnesine eklemek kadar basittir:
tvs.AnnotatorDictionary.svgTemplates['brush'] = new tvs.Template(new tvs.SvgTemplatePart( svgContent, 50, 50, '*', 'stretch' ));
Sonuçlar
Her açıklama, sayfaya mutlak konumlandırmaya sahip bir div öğesi eklenerek uygulanır:
<div class="tvs-annotate-element"> <div class="tvs-wrap-div"> <table> <tr> <td></td> <td></td> <td></td> </tr> </table> </div> </div>
Div öğesi, eklenen her hücrenin şablondaki parçalardan birine karşılık geldiği bir tabloyla doldurulur. Her şablon parçasının içeriği, seçilen renk uygulanarak Base64 kodlu veri URI'si olarak eklenir:
tvs.SvgTemplatePart.prototype.getBackground = function(color) { var image = tvs.AnnotatorCore.formatString(this.content, [color]); var encodedSVG = goog.crypt.base64.encodeString(image); return 'data:image/svg+xml;base64,' + encodedSVG; };
gömme
Daha iyi bir kullanıcı deneyimi için, özellikle bu JavaScript kitaplığını düzenlenebilir içerik alanlarıyla kullanmaya çalışırken, Metin Annotatörünün kullanıcı tarafından seçili olan metnin sınırlarını bilmesi önemlidir. Aralık ve seçim ile ilgilenen temiz bir JavaScript kitaplığı olan Rangy, bunu tarayıcılar arası bir şekilde başarmak için kullanıldı. Rangy, tüm büyük tarayıcılarda ortak DOM Aralığı ve Seçim görevlerini gerçekleştirmek için basit, standartlara dayalı bir API sağlar ve bu işlevin Internet Explorer'dan DOM uyumlu tarayıcılara kadar çok farklı uygulamalarını ortadan kaldırır. Projenin tek bağımlılığıdır.
Text Annotator yerleştirildikten sonra, onu kullanmak çok basit bir başarıdır:
var annotator = new tvs.Annotator(); annotator.underlineSelected();
Her açıklamalı eleman "tvs-annotated-text" sınıfı ile işaretlenir ve her açıklama elemanı "tvs-annotate-element" sınıfına sahiptir. Ek açıklamaları kaldırmak daha da basittir, tek satırlık:
annotator.unannotateElement(annotatedElement);
tuhaflıklar
Pencere yeniden boyutlandırıldığında, öğeler hareket edebilir ve açıklamalı öğelerin "yenilenmesini" gerektirebilir. Bu kütüphane tarafından gerçekleştirilir. Ancak; performans üzerindeki etkiyi azaltmak için ek açıklamaları yenileme çağrısı kısılır:
tvs.AnnotatorImpl = function(id, templates, positioner, options) { // ... this.throttle = new goog.Throttle(goog.bind(this.refreshAllAnnotations, this), 50); tvs.AnnotatorCore.registerForWindowResize( this.id,goog.bind(this.throttle.fire, this.throttle)); }; tvs.AnnotatorImpl.prototype.refreshAllAnnotations = function() { var elems = goog.dom.getElementsByClass(this.getCssClassForAnnotated()); var refFunc = goog.bind(this.refreshAnnotation, this); goog.array.forEach(elems, refFunc); };
Yenilemenin ardından, açıklama öğeleri gerektiği gibi eklenebilir, yeniden boyutlandırılabilir veya sayfadan kaldırılabilir.
Kolaylık
Bir sayfaya statik metne açıklama eklemeyi kolaylaştırmak için, tek ihtiyacınız olan kapsayıcı öğesindeki basit bir veri özniteliğidir:
data-annotate='underline squiggly green'
Bu, öğenin içeriğine dalgalı yeşil bir alt çizgi ile açıklama ekleyecektir.
Çözüm
Bu SVG metin öğreticisi hakkında daha ne söyleyebilirim? Eğlenceli ama güçlü bir araç kolayca uygulandı. Internet Explorer 8 için destek sağlamanın pek bir fayda sağlayacağını düşünmüyorum, çünkü bunun yerine tüm uygulamayı karmaşık hale getirebiliriz. Bununla birlikte, bazı iyileştirmeler ve çekirdek üzerinde küçük bir çalışma ile, metinsel olmayan öğeler için dekoratif bordürler üretebilmek için kütüphaneyi genişletebiliriz. Ayrıca, bir ek açıklamanın düzenlenebilir içeriğinin durumunu kaydetmek ve daha sonra geri yüklemek için bazı mekanizmalar uygulamak ilginç bir görev olabilir.
Şimdilik, olasılıklar yalnızca hayal gücünüzle (ve tarayıcı yeteneklerinizle) sınırlıdır. Belki mikro baskı çizgileri, gradyanlar ve hatta animasyonlar istiyorsunuz. Metin Annotator ile yapabilirsiniz.