2012-06-08 13 views
22

TL; DR: Chcę użyć kilku ikon wykafelkowanych w arkuszu spriterzy SVG jako obrazów tła CSS, które zachowują swój współczynnik proporcji i automatycznie skalują wypełnić element nadrzędny, używając tylko SVG i CSS. Nie JavaScript.Jak używać arkusza SVG Sprite jako obrazu tła CSS przy zachowaniu proporcji i skalowalności?


Więc mam spritesheet w formacie SVG, który zrobiłem z kombinacją SVG-Edit i pewnego ręcznego kodowania w Notepad ++. Oto kod źródłowy:

<svg version="1.1" 
    xmlns:svg="http://www.w3.org/2000/svg" 
    xmlns="http://www.w3.org/2000/svg" 
    width="600" 
    height="400" 
    viewBox="0 0 600 400"> 
    <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ --> 
    <title>chosen_sprite</title> 
    <g> 
    <title>Add</title> 
    <rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="5" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/> 
    <line id="svg_2" y2="50" x2="70" y1="50" x1="30" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/> 
    <line id="svg_3" y2="30" x2="50" y1="70" x1="50" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/> 
    </g> 
    <g> 
    <title>Delete</title> 
    <rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="105" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/> 
    <line id="svg_2" y2="70" x2="170" y1="30" x1="130" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#ff0000" fill="none"/> 
    <line id="svg_3" y2="30" x2="170" y1="70" x1="130" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#ff0000" fill="none"/> 
    </g> 
    <g> 
    <title>Expand Dark</title> 
    <rect stroke="#505050" id="svg_1" height="90" width="90" y="5" x="205" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="10" fill="none"/> 
    <line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="250" y1="65" x2="280" y2="35" id="svg_2"/> 
    <line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="220" y1="35" x2="250" y2="65" id="svg_3"/> 
    </g> 
    <g> 
    <title>Collapse Dark</title> 
    <rect stroke="#505050" height="90" width="90" y="5" x="305" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="10" fill="none" id="svg_4"/> 
    <line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="350" y1="35" x2="380" y2="65" id="svg_5"/> 
    <line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="320" y1="65" x2="350" y2="35" id="svg_6"/> 
    </g> 
    <g> 
    <title>Expand Green</title> 
    <rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="405" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/> 
    <line id="svg_2" y2="35" x2="480" y1="65" x1="450" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/> 
    <line id="svg_3" y2="65" x2="450" y1="35" x1="420" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/> 
    </g> 
    <g> 
    <title>Collapse Green</title> 
    <rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="505" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/> 
    <line id="svg_2" y2="65" x2="580" y1="35" x1="550" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/> 
    <line id="svg_3" y2="35" x2="550" y1="65" x1="520" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/> 
    </g> 
    <g> 
    <title>Search</title> 
    <circle id="svg_9" r="32" cy="140" cx="60" stroke-width="8" stroke="#000000" fill="none"/> 
    <line id="svg_11" y2="167.5" x2="32.5" y1="190" x1="10" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#000000" fill="none"/> 
    </g> 
    <g> 
    <title>Search 2</title> 
    <rect id="svg_10" stroke="#505050" height="90" width="90" y="105" x="105" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="10" fill="none"/> 
    <circle r="25" cy="142.5" cx="157.5" stroke-width="8" stroke="#000000" fill="none" id="svg_7"/> 
    <line y2="165" x2="135" y1="180" x1="120" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#000000" fill="none" id="svg_8"/> 
    </g> 
</svg> 

Działa dobrze i wygląda tak, jak chcę.

Problem to CSS. Zdefiniowanie komórek w spriteheet jest trochę bardziej niepotrzebne, niż bym chciał. Oto strona Mam wyświetlania tych ikon w:

<!DOCTYPE html> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<html> 
<head> 
<style> 

* {padding: 0px; margin: 0px; outline: 1px solid rgba(0,0,0,0.1);} 

html {width: 100%; height: 100%;} 

body {width: 100%; height: 100%;} 

.svgSprite { 
    background-image: url('./svgicons/form_icons_sprite.svg'); 
    background-repeat: no-repeat; 
    background-size: 600%; 
} 

.svgSprite.add { 
    background-position: 0px 0px; 
    width: 12px; 
    height: 12px; 
} 

.svgSprite.delete { 
    background-position: -16px 0px; 
    width: 16px; 
    height: 16px; 
} 

.svgSprite.expandDark { 
    background-position: -24px 0px; 
    width: 12px; 
    height: 12px; 
} 

.svgSprite.collapseDark { 
    background-position: -36px 0px; 
    width: 12px; 
    height: 12px; 
} 

.svgSprite.expandGreen { 
    background-position: -48px 0px; 
    width: 12px; 
    height: 12px; 
} 

.svgSprite.collapseGreen { 
    background-position: -60px 0px; 
    width: 12px; 
    height: 12px; 
} 

.svgSprite.search { 
    background-position: 0px -12px; 
    width: 12px; 
    height: 12px; 
} 

.svgSprite.search2 { 
    background-position: -16px -16px; 
    width: 16px; 
    height: 16px; 
} 

</style> 
</head> 

<body> 
<div class="svgSprite add"></div> 
<div class="svgSprite delete"></div> 
<div class="svgSprite expandDark"></div> 
<div class="svgSprite collapseDark"></div> 
<div class="svgSprite expandGreen"></div> 
<div class="svgSprite collapseGreen"></div> 
<div class="svgSprite search"></div> 
<div class="svgSprite search2"></div> 
</body> 

</html> 

Zasadniczo, chcę wiedzieć, czy istnieje prostszy sposób do określenia komórek w spritesheet i uproszczenie CSS używam powiedzieć każdy div który ikonę, aby wyświetlić z arkusza sprite.

Wolałbym, aby to rozwiązanie było ściśle SVG i CSS; Nie jestem zainteresowany korzystaniem z bibliotek JavaScript. Zamierzam doprowadzić to do punktu, w którym mogę po prostu zdefiniować komórki i ustawić konkretną ikonę, której celem jest automatyczne skalowanie w celu dopasowania jej do kontenera, przy zachowaniu proporcji. Obecnie, aby ikona pasowała do kontenera nadrzędnego, należy wyraźnie określić jej szerokość i wysokość oraz dopasować szerokość i wysokość kontenera nadrzędnego. Jeśli zmienię szerokość i wysokość kontenera nadrzędnego, muszę również zmienić rozmiary pozycji w tle.

Następnie pojawia się problem skalowania. Przy tej konfiguracji SVG skaluje się do odpowiedniego rozmiaru, który ma być narysowany na ekranie, ale jeśli zdecyduję się na powiększenie przy użyciu powiększenia przeglądarki, pikseluje. Nie jest tak, jak powinien działać SVG.

Przypuszczam, że mógłbym po prostu umieścić każdą ikonę we własnym pliku, ponieważ to wydaje się zadziałać cudownie, ale po prostu bardzo lubię używać duszków; nie tylko oszczędza mi kilku żądań serwera, jest po prostu fajny.

Jestem świadomy SVG Icon Loader. To całkiem fajne, ale jest to jeszcze jeden plik JavaScript, na którym raczej nie będę polegał.

Już odczytać docs w3 SVG, docs MDN SVG, oraz następujące wątki na SO:

SVG & Spritesheets

Fit <svg> to the size of <object> container

Using SVG as background image

... ale nawet po tym wszystkim nie udało mi się znaleźć rozwiązania.

EDYCJA: Zapomniałem wspomnieć, że musi działać w IE9. To pewna kwestia, ale wsparcie dla SVG w IE9 jest przyzwoite, dlatego wybrałem SVG do tego projektu.

+1

Podobne pytanie tutaj: http://stackoverflow.com/questions/4043809/is-there-an-equivalent-of-spriting-for-svg-images-in- strony internetowe. –

+0

Dzięki za wskaźnik. Podczas gdy ten wątek nie odpowiada dokładnie na moje pytanie, daje mi to kilka dodatkowych możliwości. Zastanawiam się, dlaczego to się nie pojawiło, kiedy szukałem? Stosy SVG wydają się być fajnym rozwiązaniem (i tak naprawdę próbowałem bardzo krótko, ale nie udało mi się go poprawnie wdrożyć). Jeśli tylko IE to wspierał. Holy crap, wydaje się działać w IE9. Zamierzam dać temu solidną, solidną próbę. Dziękuję Ci. Niestety, z jakiegoś powodu nie działa w Google Chrome, co mnie przygnębia. – Adrian

Odpowiedz

2

Zasadniczo, chcę wiedzieć, czy istnieje prostszy sposób do określenia komórek w spritesheet i uproszczenie CSS używam powiedzieć każdy div który ikonę, aby wyświetlić z spritesheet.

Nie, nie można tego zrobić łatwiej.

Spróbuj this article

Następnie istnieje problem skalowania. Przy tej konfiguracji SVG skaluje się do odpowiedniego rozmiaru, który ma być narysowany na ekranie, ale jeśli zdecyduję się na powiększenie przy użyciu powiększenia przeglądarki, pikseluje. Nie jest tak, jak powinien działać SVG.

W Chromium 18 wygląda całkiem dobrze - bez żadnych pikseli.

W mojej liście przeglądarek badań (FF3.6 Opera 9.2 IE6) nie widziałem, co widziałem w Chromium

I o IE9, być może problem w engine

+0

Chociaż ta odpowiedź nie rozwiązała mojego problemu, wyjaśniła kilka rzeczy i zdałam sobie sprawę, że powinienem oznaczyć to pytanie jako udzielone. Powyższy komentarz autorstwa @Erika był bardziej przydatny na dłuższą metę, zapewniając realną alternatywę, ale nie mogę oznaczyć komentarza jako odpowiedzi. – Adrian

+0

@Adrian Jeśli nie masz prawdziwych odpowiedzi na swoje pytanie, możesz opublikować własne i oznaczyć je jako rozwiązanie. Dzięki i tak – nk9

+1

Połączony przykład niestety nie działa w chrome. – Amalgovinus

7

Jeśli ikony mają taką samą wielkość możesz wykonać następujące czynności:

  1. Spakuj swoje ikony w sprite w poziomie (użyj svg-sprite, jeśli ikony znajdują się w oddzielnych plikach).
  2. Ustaw background-size: auto 100%; dla selektora celu.
  3. Ustawia docelowe elementy "width, height lub font-size dla skali.

.icon { 
 
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="16" viewBox="0 0 64 16"> <circle fill="blue" cx="8" cy="8" r="8"/> <circle fill="red" cx="24" cy="8" r="8"/> <circle fill="yellow" cx="40" cy="8" r="8"/> <circle fill="green" cx="56" cy="8" r="8"/> </svg>'); 
 
    background-repeat: no-repeat; 
 
    background-size: auto 100%; 
 
    display: inline-block; 
 
} 
 
.icon.small { 
 
    height: 1em; 
 
    width: 1em; 
 
} 
 
.icon.medium { 
 
    height: 2em; 
 
    width: 2em; 
 
} 
 
.icon.large { 
 
    height: 4em; 
 
    width: 4em; 
 
} 
 
.icon_1 { 
 
    background-position: 0 0; 
 
} 
 
.icon_2 { 
 
    background-position: 33.33% 0; 
 
} 
 
.icon_3 { 
 
    background-position: 66.67% 0; 
 
} 
 
.icon_4 { 
 
    background-position: 100% 0; 
 
}
<span class="icon icon_1 small"></span> 
 
<span class="icon icon_1 medium"></span> 
 
<span class="icon icon_2 large"></span>

+0

To podejście działa, ale z jakiegoś powodu wartości procentowe nie działają. SVG jest ustawiony na 5%, 10% itp., Ale nie wyświetli się poprawnie, chyba że użyję 5,2%, 10,4%, 15,7% itd. Piksele działają jednak dobrze (20 pikseli, 40 pikseli, itd.). Myśli? – johnkeese

+0

@johnkeese Myślę, że potrzebujesz ustawienia 'preserveAspectRatio =" none "' dla głównego węzła SVG. Jeśli używasz svg-sprite, użyj tej opcji: '{rootAttributes: {'preserveAspectRatio': 'none'}}'. Ale nadal należy skalować ikony proporcjonalnie do minimalnego rozmiaru, w przeciwnym razie krawędzie ikony będą interpolowane między pikselami i będą niewyraźne. –

+0

@johnkeese Spróbuj także 'shape-rendering =" crispEdges "'. –

Powiązane problemy