Jak sprawić, by element <svg> rozszerzał się lub zmniejszał do swojego kontenera nadrzędnego?

112

Celem jest <svg>rozwinięcie elementu do rozmiaru jego kontenera nadrzędnego, w tym przypadku a <div>, bez względu na to, jak duży lub mały może być ten kontener.

Kod:

<style>
    svg, #container{
        height: 100%;
        width: 100%;
    }
</style>

<div id="container">
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" >
         <rect x="0" y="0" width="100" height="100" />
    </svg>
</div>

Najczęstszym rozwiązaniem tego problemu wydaje się być ustawienie viewBoxatrybutu na <svg>elemencie.

viewBox="0 0 widthOfContainer heightOfContainer"

Jednak wydaje się, że nie działa to w przypadkach, gdy elementy w <svg>elemencie mają wstępnie zdefiniowane szerokości i / lub wysokości. Na przykład <rect>element w powyższym kodzie ma jawnie ustawioną szerokość i wysokość.

Więc oczywistym rozwiązaniem jest użycie% szerokości i% wysokości również dla tych elementów. Ale czy to w ogóle trzeba zrobić? Zwłaszcza, że <img src=test.svg >działa dobrze i rozszerza się / kurczy bez żadnych problemów z wyraźnie określonymi <rect>wysokościami i szerokościami.

Jeśli elementy takie jak <rect>i inne podobne elementy muszą mieć swoje szerokości i wysokości zdefiniowane w procentach, czy istnieje sposób w Inkscape, aby ustawić to tak, aby wszystkie elementy w <svg>dokumencie używały procentowych szerokości, wysokości itp. Zamiast stałych wymiarów ?

user782860
źródło
1
Zapisz plik svg jako plik, a następnie odwołaj się do niego jako obrazu, na przykład <img src = "file.svg" /> iw ten sposób możesz użyć szerokości: 100% lub wysokości: 100%
Burimi

Odpowiedzi:

56

To viewBoxnie jest wysokość pojemnika, to rozmiar twojego rysunku. Określ swoją viewBoxszerokość na 100 jednostek, a następnie zdefiniuj rectją na 10 jednostek. Następnie, bez względu na to, jak duży zostanie skalowany SVG, rectszerokość obrazu będzie wynosić 10%.

robertc
źródło
33
Ale pytanie brzmi: jak skalować SVG?
Adrian Heine,
6
@AdrianLang Skalowanie odbywa się automatycznie po ustawieniu rozmiaru obiektu SVG, tak jak zostało to już zrobione w kodzie w pytaniu. Oto poprawiona wersja przykładu .
robertc
Masz rację, świetnie, to naprawdę działa na mnie. Myślę, że moim problemem były właściwości wysokości i szerokości w moim głównym elemencie svg.
Adrian Heine
2
Zrobiłem kilka drobnych poprawek na tych skrzypcach, aby zmiana rozmiaru była wymuszana w poziomie i w pionie bez zachowania proporcji, i sprawiłem, że działało w IE, podczas gdy przesłane skrzypce @robertc nie. Mam nadzieję, że pomoże to komuś w drodze!
Mister Crimson,
3
Domyślnie twój plik SVG będzie skalowany tak duży, jak to możliwe, aby był całkowicie widoczny, ale zachowuje proporcje (więc kwadratowy ViewBox nie wypełni całkowicie prostokątnego elementu nadrzędnego). Jeśli naprawdę chcesz wymusić całkowite zakrycie kontenera nadrzędnego, dodaj preserveAspectRatio = "none" do elementu SVG.
patricksurry
24

Załóżmy, że mam plik SVG, który wygląda tak: pic1

Chcę umieścić go w elemencie div i sprawić, by odpowiadał za jego wypełnienie. Mój sposób na to jest następujący:

Najpierw otwieram plik SVG w aplikacji takiej jak inkscape. W menu Plik-> Właściwości dokumentu ustawiam szerokość dokumentu na 800px i wysokość na 600px (możesz wybrać inne rozmiary). Następnie dopasowuję SVG do tego dokumentu.

pic2

Następnie zapisuję ten plik jako nowy plik SVG i pobieram dane ścieżki z tego pliku. Teraz w HTML kod, który robi magię, wygląda następująco:

<div id="containerId">    
    <svg
    id="svgId" 
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    x="0"
    y="0"
    width="100%"
    height="100%"
    viewBox="0 0 800 600"
    preserveAspectRatio="none">
       <path d="m0 0v600h800v-600h-75.07031l-431 597.9707-292.445315-223.99609 269.548825-373.97461h-271.0332z" fill="#f00"/>
    </svg>
</div>

Zwróć uwagę, że szerokość i wysokość SVG są ustawione na 100%, ponieważ chcemy, aby wypełniał kontener w pionie i poziomie, ale szerokość i wysokość viewBox są takie same jak szerokość i wysokość dokumentu w inkscape, która wynosi 800 pikseli X 600px. Następną rzeczą, którą musisz zrobić, jest ustawienie parametru preserveAspectRatio na „none”. Jeśli potrzebujesz więcej informacji na temat tego atrybutu, oto dobry link . I to wszystko.

Co więcej, ten kod działa na prawie wszystkich głównych przeglądarkach, nawet starych, ale w niektórych wersjach Androida i iOS musisz użyć kodu javascrip / jQuery, aby zachować spójność. Używam następujących funkcji w funkcji Document Ready i Resize:

$('#svgId').css({
    'width': $('#containerId').width() + 'px',
    'height': $('#containerId').height() + 'px'
});

Mam nadzieję, że to pomoże!

Reza Baradaran Gazorisangi
źródło
5
+1 za uwagę zachowawcząAspectRatio. Po polowaniu na wysokie i niskie, aby plik SVG faktycznie rozciągał się (nie skalował) do elementu div, była to poprawna odpowiedź.
adelphus
@Gazoris, Dzięki za tę wspaniałą odpowiedź. mam pytanie na ten sam temat. Co jeśli mój plik SVG jest zagnieżdżony. na przykład <svg> <svg id = "1"> </svg> <svg id = "2"> </svg> </svg> chcę warunkowo wyświetlić svg 1 i 2 i powinien on mieć szerokość i wysokość kontenera. <div id = "container" style = "width: 200px; height: 200px;"> </div> czy możesz mi w tym pomóc.
Prasad Parab
@Reza Baradaran: Genius.
DanMad,
6

Ostatnio pomogło mi usunięcie wszystkich atrybutów height=""i width=""z <svg>tagu oraz wszystkich tagów podrzędnych. Następnie możesz użyć skalowania na podstawie wartości procentowej wysokości lub szerokości kontenera nadrzędnego.

Geoff Colbath
źródło
5
Czy możesz podać działający przykład? Nie mogę tego zrobić.
Michael
2

@robertc ma rację, ale musisz również zauważyć, że svg, #containerpowoduje to, że svg jest skalowane wykładniczo do czegokolwiek innego niż 100% (raz na #containerzawsze svg).

Innymi słowy, gdybym zastosował 50% h / w do obu elementów, to w rzeczywistości jest to 50% z 50% lub .5 * .5, co równa się 0,25 lub 25% skali.

Jeden selektor działa dobrze, gdy jest używany zgodnie z sugestią @robertc.

svg {
  width:50%;
  height:50%;
}
Justin Putney
źródło
To dlatego, że selektor svg, #containerpasuje zarówno do svgelementu DOM oraz z #containerelementu DOM. Wydaje mi się, że zamiast tego szukałeś svg #container, ale określenie rodzica nie jest konieczne, jeśli i tak używasz identyfikatora.
Nit
Czy to nie jest dokładnie to, co powiedziałem, „raz na #container i raz na svg”?
Justin Putney,
1
Och, przepraszam, masz rację, ale twoja odpowiedź jest nieco dziwnie sformułowana, co prowadzi do nieporozumienia. Na początku brzmi to tak, jakbyś mówił o potencjalnej wpadce.
Nit
1

Dla twojego iphone'a możesz użyć w swojej głowie:

"width=device-width"
Vincent
źródło