paint-brush
Simgelerle SVG Sprite Nasıl Oluşturulurby@gmakarov
3,865
3,865

Simgelerle SVG Sprite Nasıl Oluşturulur

German Makarov10m2023/12/23
Read on Terminal Reader

Geliştiriciler genellikle SVG'yi doğrudan JSX'e ekler. Bunun kullanımı kolaydır ancak JS paket boyutunu artırır. Optimizasyon arayışı içinde, paketi karmaşıklaştırmadan SVG simgelerini kullanmanın başka bir yolunu bulmaya karar verdim. SVG sprite'larının ne olduğu, nasıl kullanılacağı ve onlarla çalışmak için hangi araçların mevcut olduğu hakkında konuşacağız. Teoriyle başlayarak, adım adım bir SVG sprite oluşturan bir komut dosyası yazacağız ve vite ve webpack eklentilerini tartışarak sonlandıracağız.
featured image - Simgelerle SVG Sprite Nasıl Oluşturulur
German Makarov HackerNoon profile picture

Geliştiriciler genellikle SVG'yi doğrudan JSX'e ekler. Bunun kullanımı kolaydır ancak JS paket boyutunu artırır. Optimizasyon arayışı içinde, paketi karmaşıklaştırmadan SVG simgelerini kullanmanın başka bir yolunu bulmaya karar verdim. SVG sprite'larının ne olduğu, nasıl kullanılacağı ve onlarla çalışmak için hangi araçların mevcut olduğu hakkında konuşacağız.


Teoriden başlayarak, adım adım bir SVG sprite oluşturan bir komut dosyası yazacağız ve vite ve webpack için eklentileri tartışarak sonlandıracağız.

SVG Sprite Nedir?

Bir görüntü grafiği, tek bir görüntüye yerleştirilen görüntülerin koleksiyonudur. SVG Sprite ise <symbol /> içine sarılmış ve <svg /> içine yerleştirilmiş bir SVG içeriği koleksiyonudur.


Örneğin basit bir SVG kalem simgemiz var:


Bir SVG hareketli grafiği elde etmek için <svg /> etiketini <symbol /> ile değiştireceğiz ve onu harici olarak <svg /> ile saracağız:

Artık bu bir SVG hareketli grafiği ve içinde id="icon-pen" olan bir simgemiz var.


Tamam ama bu simgeyi HTML sayfamıza nasıl yerleştireceğimizi bulmalıyız. Simgenin kimliğini belirten <use /> etiketini href özelliğiyle birlikte kullanacağız ve bu öğeyi SVG'nin içinde kopyalayacağız.


<use /> nasıl çalıştığına dair bir örneğe bakalım:

Bu örnekte iki daire var. Birincisi mavi bir çerçeveye sahip, ikincisi ise ilkinin kopyası ancak kırmızı dolgulu.


SVG sprite'ımıza geri dönelim. <use /> kullanımıyla birlikte şunu elde edeceğiz:

Burada kalem simgemizin bulunduğu bir düğmemiz var.


Şu ana kadar <button /> da kodu olmayan bir simge kullandık. Sayfada birden fazla düğmemiz varsa, bu durum HTML düzenimizin boyutunu birden fazla etkilemeyecektir çünkü tüm simgeler SVG sprite'ımızdan gelecektir ve yeniden kullanılabilir olacaktır.

SVG Sprite Dosyası Oluşturma

index.html dosyasını karmaşıklaştırmamak için SVG sprite'ımızı ayrı bir dosyaya taşıyalım. Öncelikle bir sprite.svg dosyası oluşturun ve içine bir SVG sprite yerleştirin. Bir sonraki adım, <use/> içindeki href özelliğini kullanarak simgeye erişim sağlamaktır:

SVG Sprite Oluşturmayı Otomatikleştirme

Simge kullanımında çok fazla zaman kazanmak için bu işlem için bir otomasyon ayarlayalım. Simgelere kolay erişim sağlamak ve onları istediğimiz gibi yönetmek için, her birinin kendi dosyasında ayrılması gerekir.


Öncelikle tüm simgeleri aynı klasöre koymalıyız, örneğin:

Şimdi bu dosyaları alan ve bunları tek bir SVG grafiğinde birleştiren bir komut dosyası yazalım.


  1. Projenizin kök dizininde generateSvgSprite.ts dosyasını oluşturun.


  2. Glob kitaplığını yükleyin:

     npm i -D glob


  3. globSync kullanarak her simge için bir dizi tam yol elde edin:

  4. Şimdi, her dosya yolunu yineleyeceğiz ve Node'un yerleşik fs kitaplığını kullanarak dosya içeriğini alacağız:

    Harika, her simgenin SVG koduna sahibiz ve artık bunları birleştirebiliriz, ancak her simgenin içindeki svg etiketini symbol etiketiyle değiştirmeli ve gereksiz SVG niteliklerini kaldırmalıyız.


  5. DOM gösterimini elde etmek için SVG kodumuzu bazı HTML ayrıştırıcı kütüphaneleriyle ayrıştırmalıyız. node-html-parser'ı kullanacağım:

    SVG kodunu ayrıştırdık ve SVG öğesini gerçek bir HTML öğesiymiş gibi elde ettik.


  6. Aynı ayrıştırıcıyı kullanarak, svgElement öğesinin alt öğelerini symbol öğesine taşımak için boş bir symbol öğesi oluşturun:

  7. Çocukları svgElement çıkardıktan sonra, id ve viewBox özelliklerini de almalıyız. id olarak ikon dosyasının ismini belirleyelim.

  8. Artık bir SVG hareketli grafiğine yerleştirilebilecek bir symbol öğemiz var. Bu nedenle, dosyaları yinelemeden önce symbols değişkenini tanımlayın, symbolElement öğesini bir dizeye dönüştürün ve symbols aktarın:

  9. Son adım, SVG grafiğinin kendisini oluşturmaktır. “Kök”te svg ve alt öğeler olarak semboller bulunan bir dizeyi temsil eder:

     const svgSprite = `<svg>${symbols.join('')}</svg>`;


    Aşağıda bahsedeceğim eklentileri kullanmayı düşünmüyorsanız, oluşturulan hareketli grafiğin bulunduğu dosyayı statik bir klasöre koymanız gerekir. Paketleyicilerin çoğu public klasör kullanır:

     fs.writeFileSync('public/sprite.svg', svgSprite);


Ve işte bu; komut dosyası kullanıma hazır:

 // generateSvgSprite.ts import { globSync } from 'glob'; import fs from 'fs'; import { HTMLElement, parse } from 'node-html-parser'; import path from 'path'; const svgFiles = globSync('src/icons/*.svg'); const symbols: string[] = []; svgFiles.forEach(file => { const code = fs.readFileSync(file, 'utf-8'); const svgElement = parse(code).querySelector('svg') as HTMLElement; const symbolElement = parse('<symbol/>').querySelector('symbol') as HTMLElement; const fileName = path.basename(file, '.svg'); svgElement.childNodes.forEach(child => symbolElement.appendChild(child)); symbolElement.setAttribute('id', fileName); if (svgElement.attributes.viewBox) { symbolElement.setAttribute('viewBox', svgElement.attributes.viewBox); } symbols.push(symbolElement.toString()); }); const svgSprite = `<svg>${symbols.join('')}</svg>`; fs.writeFileSync('public/sprite.svg', svgSprite);


Bu betiği projenizin kök dizinine yerleştirebilir ve tsx ile çalıştırabilirsiniz:

 npx tsx generateSvgSprite.ts


Aslında burada tsx kullanıyorum çünkü eskiden her yerde TypeScript'te kod yazıyordum ve bu kütüphane TypeScript'te yazılmış düğüm komut dosyalarını çalıştırmanıza izin veriyor. Saf JavaScript kullanmak istiyorsanız şunu çalıştırabilirsiniz:

 node generateSvgSprite.js


Şimdi betiğin ne yaptığını özetleyelim:

  • Herhangi bir .svg dosyası için src/icons klasörüne bakar.


  • Her simgenin içeriğini çıkarır ve ondan bir sembol öğesi oluşturur.


  • Tüm sembolleri tek bir <svg />.


  • public klasörde sprite.svg dosyası oluşturur.

Simge Renkleri Nasıl Değiştirilir

Sık karşılaşılan ve önemli bir durumu ele alalım: renkler! Simgenin bir hareketli grafik haline geldiği bir komut dosyası oluşturduk ancak bu simge, proje boyunca farklı renklere sahip olabilir.


Yalnızca <svg/> öğelerinin dolgu veya kontur niteliklerine sahip olabileceğini değil aynı zamanda path , circle , line ve diğer öğelerin de olabileceğini aklımızda tutmalıyız. Bize yardımcı olacak çok kullanışlı bir CSS özelliği var - currentcolor .


Bu anahtar kelime, bir öğenin renk özelliğinin değerini temsil eder. Örneğin, background: currentcolor olan bir öğe üzerinde color: red rengini kullanırsak, bu öğenin arka planı kırmızı olur.


Temel olarak, her kontur veya dolgu öznitelik değerini currentcolor olarak değiştirmemiz gerekir. Umarım bunun manuel olarak yapıldığını görmüyorsunuzdur, heh. Hatta SVG dizelerini değiştirecek veya ayrıştıracak bazı kodlar yazmak bile çok kullanışlı bir araç olan svgo ile karşılaştırıldığında çok verimli değildir.


Bu, yalnızca renkler konusunda değil aynı zamanda SVG'deki gereksiz bilgilerin kaldırılmasında da yardımcı olabilecek bir SVG optimize edicidir.


Svgo'yu yükleyelim:

 npm i -D svgo


svgo yerleşik eklentileri vardır ve bunlardan biri, currentColor: true özelliğine sahip olan convertColors . Bu SVG çıktısını kullanırsak renkleri currentcolor ile değiştirecektir. convertColors ile birlikte svgo kullanımı şöyledir:

 import { optimize } from 'svgo'; const output = optimize( '<svg viewBox="0 0 24 24"><path fill="#000" d="m15 5 4 4" /></svg>', { plugins: [ { name: 'convertColors', params: { currentColor: true, }, } ], } ) console.log(output);


Ve çıktı şöyle olacaktır:

 <svg viewBox="0 0 24 24"><path fill="currentColor" d="m15 5 4 4"/></svg>


Bir önceki bölümde yazdığımız sihirli scriptimize svgo ekleyelim:

 // generateSvgSprite.ts import { globSync } from 'glob'; import fs from 'fs'; import { HTMLElement, parse } from 'node-html-parser'; import path from 'path'; import { Config as SVGOConfig, optimize } from 'svgo'; // import `optimize` function const svgoConfig: SVGOConfig = { plugins: [ { name: 'convertColors', params: { currentColor: true, }, } ], }; const svgFiles = globSync('src/icons/*.svg'); const symbols: string[] = []; svgFiles.forEach(file => { const code = fs.readFileSync(file, 'utf-8'); const result = optimize(code, svgoConfig).data; // here goes `svgo` magic with optimization const svgElement = parse(result).querySelector('svg') as HTMLElement; const symbolElement = parse('<symbol/>').querySelector('symbol') as HTMLElement; const fileName = path.basename(file, '.svg'); svgElement.childNodes.forEach(child => symbolElement.appendChild(child)); symbolElement.setAttribute('id', fileName); if (svgElement.attributes.viewBox) { symbolElement.setAttribute('viewBox', svgElement.attributes.viewBox); } symbols.push(symbolElement.toString()); }); const svgSprite = `<svg xmlns="http://www.w3.org/2000/svg">${symbols.join('')}</svg>`; fs.writeFileSync('public/sprite.svg', svgSprite);


Ve betiği çalıştırın:

 npx tsx generateSvgSprite.ts


Sonuç olarak SVG hareketli grafiği, currentColor özelliğine sahip simgeler içerecektir. Ve bu simgeler projenin her yerinde istediğiniz renkle kullanılabilmektedir.

Eklentiler

Elimizde bir script var ve onu istediğimiz zaman çalıştırabiliyoruz ama manuel olarak kullanmamız biraz sakıncalı. Bu nedenle, .svg dosyalarımızı izleyebilecek ve hareket halindeyken SVG sprite'ları oluşturabilecek birkaç eklenti öneririm:


  1. vite-plugin-svg-spritemap ( vite kullanıcıları için)

    Bu, temelde bu makalede az önce oluşturduğumuz betiği içeren eklentim. Eklentinin currentColor değişimi varsayılan olarak etkindir, böylece eklentiyi oldukça kolay bir şekilde kurabilirsiniz.

     // vite.config.ts import svgSpritemap from 'vite-plugin-svg-spritemap'; export default defineConfig({ plugins: [ svgSpritemap({ pattern: 'src/icons/*.svg', filename: 'sprite.svg', }), ], });


  2. svg-spritemap-webpack-eklentisi ( webpack kullanıcıları için)

    Vite'a geçene kadar bu Webpack eklentisini kullandım. Ancak Webpack kullanıyorsanız bu eklenti hala iyi bir çözümdür. Renk dönüşümünü manuel olarak etkinleştirmelisiniz; şu şekilde görünecektir:

     // webpack.config.js const SVGSpritemapPlugin = require('svg-spritemap-webpack-plugin'); module.exports = { plugins: [ new SVGSpritemapPlugin('src/icons/*.svg', { output: { svgo: { plugins: [ { name: 'convertColors', params: { currentColor: true, }, }, ], }, filename: 'sprite.svg', }, }), ], }

Mizanpajda Kullanım

React'ta bir örnek vereceğim ama çoğunlukla HTML ile ilgili olduğu için istediğiniz yere uygulayabilirsiniz. Dolayısıyla, derleme klasörümüzde sprite.svg bulunduğundan, hareketli resim dosyasına erişebilir ve temel Icon bileşenini oluşturabiliriz:

 const Icon: FC<{ name: string }> = ({ name }) => ( <svg> <use href={`/sprite.svg#${name}`} /> </svg> ); const App = () => { return <Icon name="pen" />; };

Nihai Sonuç

Dolayısıyla, simgelerle yapılan birçok manuel çalışmayı önlemek için her şeyi özetleyerek şunları yapıyoruz:

  • projedeki düzenli simgeleri istenen adlarla kolayca kaydedebilir ve saklayabilir


  • tüm simgeleri ayrı bir dosyada tek bir hareketli grafikte birleştiren, paket boyutunu azaltan ve bu simgeleri projenin herhangi bir yerinde kullanmamıza olanak tanıyan bir komut dosyasına sahip olmak


  • simgeleri gereksiz özelliklerden uzak tutmamıza ve kullanım yerinde renkleri değiştirmemize yardımcı olan kullanışlı bir araca sahibiz


  • oluşturma sürecinin bir parçası olarak simge dosyalarımızı izleyebilecek ve hareket halindeyken sprite oluşturabilecek bir eklentiye sahip olmak


  • üstünde kiraz olan bir Icon bileşeni var

Çözüm

Geliştirmede verimlilik yalnızca zamandan tasarruf etmekle ilgili değildir; bu, yaratıcı potansiyelimizin kilidini açmakla ilgilidir. Simgeleri yönetmek gibi hassas görevleri otomatikleştirmek yalnızca bir kısayol değildir; daha sorunsuz, daha etkili bir kodlama deneyimine açılan bir kapıdır. Bu tür rutin işlerde zaman kazanarak daha karmaşık görevlere odaklanabilir ve bir geliştirici olarak daha hızlı büyüyebilirsiniz.