Wie kann ich mit dem übergeordneten Container eine SVG-Skala erstellen?

235

Ich möchte die Inhaltsskala eines Inline-SVG-Elements haben, wenn die Größe nicht nativ ist. Natürlich könnte ich es als separate Datei haben und es so skalieren.

index.html: <img src="foo.svg" style="width: 100%;" />

foo.svg: <svg width="123" height="456"></svg>

Ich möchte dem SVG jedoch zusätzliche Stile über CSS hinzufügen, sodass das Verknüpfen eines externen Stils keine Option ist. Wie erstelle ich eine Inline-SVG-Skala?

bjb568
quelle
2
Versuchen Sie Präzedenzfälle in SVG-Breiten und -Höhen.
ncm
@ncm Wie würde es mit JS gemacht werden?
Mawg sagt, Monica

Antworten:

456

Um die Koordinaten innerhalb der SVG - Datei unabhängig von der skalierte Größe des Bildes zu bestimmen, verwenden Sie das viewBoxAttribut auf dem SVG - Element zu definieren , was der Begrenzungsrahmen des Bildes in dem System der Bildkoordinaten ist, und verwendet die widthund heightAttribute zu definieren , was Die Breite oder Höhe beziehen sich auf die enthaltene Seite.

Zum Beispiel, wenn Sie Folgendes haben:

<svg>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

Es wird als 10 x 20 Pixel großes Dreieck gerendert:

10x20 Dreieck

Wenn Sie nun nur die Breite und Höhe festlegen, wird die Größe des SVG-Elements geändert, das Dreieck jedoch nicht skaliert:

<svg width=100 height=50>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

10x20 Dreieck

Wenn Sie das Ansichtsfeld festlegen, wird das Bild so transformiert, dass das angegebene Feld (im Koordinatensystem des Bildes) so skaliert wird, dass es in die angegebene Breite und Höhe (im Koordinatensystem der Seite) passt. So skalieren Sie das Dreieck beispielsweise auf 100 x 50 Pixel:

<svg width=100 height=50 viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

100x50 Dreieck

Wenn Sie es auf die Breite des HTML-Ansichtsfensters skalieren möchten:

<svg width="100%" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

300x150 Dreieck

Beachten Sie, dass das Seitenverhältnis standardmäßig beibehalten wird. Wenn Sie also angeben, dass das Element eine Breite von 100%, aber eine Höhe von 50 Pixel haben soll, wird es tatsächlich nur auf die Höhe von 50 Pixel skaliert (es sei denn, Sie haben ein sehr schmales Fenster):

<svg width="100%" height="50px" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

100x50 Dreieck

Wenn Sie möchten, dass es sich horizontal erstreckt, deaktivieren Sie die Beibehaltung des Seitenverhältnisses mit preserveAspectRatio=none:

<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

300x50 Dreieck

(Beachten Sie, dass ich in meinen Beispielen eine Syntax verwende, die für die HTML-Einbettung funktioniert. Um die Beispiele als Bild in StackOverflow aufzunehmen, binde ich sie stattdessen in eine andere SVG-Datei ein. Daher muss ich eine gültige XML-Syntax verwenden.)

Brian Campbell
quelle
1
Wie macht man nicht nur die viewBoxerveAspectRatio, sondern auch die Hauptbox? Ich möchte Breite: 100%; Höhe: Auto dafür.
bjb568
1
@Dude: Ich denke, dass das Beispiel mit width="100%"und ohne angegebene Höhe das tut, was Sie wollen. Ich habe Bilder hinzugefügt, um zu demonstrieren. Es hat eine Breite von 100% und vergrößert die Höhe proportional. Wenn das nicht das ist, wonach Sie suchen, können Sie versuchen zu klären, was Sie gemeint haben?
Brian Campbell
1
Oh. Eigentlich kein Problem. Es ist nur ein Webkit-Fehler. In Safari und Chrome beträgt die "echte" Höhe standardmäßig 100% und nicht automatisch. Wie würde ich das dann umgehen?
bjb568
4
@Dude Ah, ja, ich verstehe. In Firefox funktioniert es einwandfrei, aber kein Chrome oder Safari. Gemäß der SVG-Spezifikation scheint Firefox korrekt zu sein. Während der Standardwert von widthund heightfür ein SVG-Element 100% ist, ist dies nicht die CSS-Definition von 100% (100% des enthaltenden Blocks), sondern 100% des Ansichtsfensters, das basierend auf dem intrinsischen Seitenverhältnis angegeben wurde ( was aus dem viewBoxZeitpunkt berechnet wird, zu dem dies gegeben ist). Ich habe noch keine Lösung für dieses Problem gefunden, das in Chrome / Safari funktioniert.
Brian Campbell
1
Das funktioniert bei mir. Ich erstelle zuerst ein viewBox-Attribut für das SVG-Element und setze den Wert auf "0 0 [ursprüngliche SVG-Breite] [ursprüngliche SVG-Höhe]". Als nächstes ändere ich das width-Attribut des SVG-Elements in "auto" und das height-Attribut in "100%". Der Container muss auch eine definierte Höhe haben. Dadurch wird der Vektor auf 100% der Containerhöhe skaliert, sodass die Breite schweben kann. Stellen Sie abschließend die maximale CSS-Breite des SVG auf 100% ein, um ein Überschießen des Containers zu verhindern.
Ryan Griggs
28

Nach ungefähr 48 Stunden Recherche habe ich dies getan, um eine proportionale Skalierung zu erhalten:

HINWEIS: Dieses Beispiel wurde mit React geschrieben. Wenn Sie nicht , dass sind, ändern Sie das Kamel Fall Sachen zurück zu Bindestriche (dh: Änderung backgroundColorzu background-colorund ändern Sie den Stil Objectauf eine Rückseite String).

<div
  style={{
    backgroundColor: 'lightpink',
    resize: 'horizontal',
    overflow: 'hidden',
    width: '1000px',
    height: 'auto',
  }}
>
  <svg
    width="100%"
    viewBox="113 128 972 600"
    preserveAspectRatio="xMidYMid meet"
  >
    <g> ... </g>
  </svg>
</div>

Folgendes passiert im obigen Beispielcode:

VIEWBOX

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox

min-x, min-y, Breite und Höhe

dh: viewbox = "0 0 1000 1000"

Viewbox ist ein wichtiges Attribut, da es der SVG grundsätzlich mitteilt, welche Größe wo gezeichnet werden soll. Wenn Sie CSS verwendet haben, um das SVG 1000x1000 px zu erstellen, Ihre Ansichtsbox jedoch 2000x2000 war, wird das obere linke Viertel Ihres SVG angezeigt .

Die ersten beiden Zahlen, min-x und min-y, bestimmen, ob die SVG innerhalb des Ansichtsfelds versetzt werden soll.

Mein SVG muss nach oben / unten oder links / rechts verschoben werden

Untersuchen Sie dies: viewbox = "50 50 450 450"

Die ersten beiden Zahlen verschieben Ihr SVG um 50 Pixel nach links und um 50 Pixel nach oben, und die zweiten beiden Zahlen haben die Größe des Ansichtsfelds: 450 x 450 Pixel. Wenn Ihre SVG-Datei 500 x 500 ist, aber zusätzliche Auffüllungen aufweist, können Sie diese Zahlen manipulieren, um sie in der "Ansichtsbox" zu verschieben.

Ihr Ziel an dieser Stelle ist es, eine dieser Zahlen zu ändern und zu sehen, was passiert.

Sie können das Ansichtsfeld auch vollständig weglassen, aber Ihr Kilometerstand hängt von jeder anderen Einstellung ab, die Sie zu diesem Zeitpunkt haben. Nach meiner Erfahrung treten Probleme beim Beibehalten des Seitenverhältnisses auf, da das Ansichtsfeld beim Definieren des Seitenverhältnisses hilft.

ASPEKTVERHÄLTNIS ERHALTEN

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio

Basierend auf meinen Recherchen gibt es viele verschiedene Einstellungen für das Seitenverhältnis, aber die Standardeinstellung wird aufgerufen xMidYMid meet. Ich lege es auf meine, um mich ausdrücklich daran zu erinnern. xMidYMid meetLässt es proportional zum Mittelpunkt X und Y skalieren. Dies bedeutet, dass es in der Ansichtsbox zentriert bleibt.

BREITE

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/width

Schauen Sie sich meinen Beispielcode oben an. Beachten Sie, wie ich nur Breite, keine Höhe einstelle. Ich habe es auf 100% gesetzt, damit es den Container füllt, in dem es sich befindet. Dies trägt wahrscheinlich am meisten zur Beantwortung dieser Frage zum Stapelüberlauf bei.

Sie können es auf einen beliebigen Pixelwert ändern, aber ich würde empfehlen, 100% zu verwenden, um die maximale Größe zu erreichen und es dann mit CSS über den übergeordneten Container zu steuern. Ich empfehle dies, weil Sie "richtige" Kontrolle erhalten. Sie können Medienabfragen verwenden und die Größe ohne verrücktes JavaScript steuern.

Skalieren mit CSS

Schauen Sie sich meinen Beispielcode oben noch einmal an. Beachten Sie, wie ich diese Eigenschaften habe:

resize: 'horizontal', // you can safely omit this
overflow: 'hidden',   // if you use resize, use this to fix weird scrollbar appearance
width: '1000px',
height: 'auto',

Dies ist zusätzlich, zeigt Ihnen jedoch, wie Sie dem Benutzer erlauben können, die Größe des SVG zu ändern, während das richtige Seitenverhältnis beibehalten wird. Da das SVG sein eigenes Seitenverhältnis beibehält, müssen Sie nur die Breite des übergeordneten Containers ändern, und die Größe wird wie gewünscht geändert.

Wir lassen die Höhe in Ruhe und / oder stellen sie auf Auto ein und steuern die Größenänderung mit der Breite. Ich habe die Breite ausgewählt, weil sie aufgrund reaktionsschneller Designs oft aussagekräftiger ist.

Hier ist ein Bild dieser Einstellungen, die verwendet werden:

Geben Sie hier die Bildbeschreibung ein

Wenn Sie jede Lösung in dieser Frage gelesen haben und immer noch verwirrt sind oder nicht genau wissen, was Sie brauchen, lesen Sie diesen Link hier. Ich fand es sehr hilfreich:

https://css-tricks.com/scale-svg/

Es ist ein riesiger Artikel, der jedoch so gut wie jede Möglichkeit zur Manipulation einer SVG mit oder ohne CSS aufschlüsselt. Ich empfehle es zu lesen, während Sie beiläufig einen Kaffee oder eine Auswahl ausgewählter Flüssigkeiten trinken.

agm1984
quelle
Dies scheint bei keinem SVG zu funktionieren. Wenn Sie keine Kontrolle über die SVG-Quelle haben, schlägt diese Methode fehl, wenn das SVG eine feste Breite hat.
user48956
@ user48956 Sie können es jederzeit nachträglich mit JavaScript bearbeiten.
Andrew
Ja - Sie können mit einer Programmierung immer in die Innereien verschiedener Dateiformate stöbern - aber Sie hoffen, dass es eine Methode gibt, die für alle Arten von Assets (z. B. PNGs) funktioniert und keine JavaScript-Programmierung erfordert.
user48956
20

Sie möchten eine Transformation als solche durchführen:

mit JavaScript:

document.getElementById(yourtarget).setAttribute("transform", "scale(2.0)");

Mit CSS:

#yourtarget {
  transform:scale(2.0);
  -webkit-transform:scale(2.0);
}

Wickeln Sie Ihre SVG-Seite in ein Gruppen-Tag als solches ein und zielen Sie darauf ab, die gesamte Seite zu bearbeiten:

<svg>
  <g id="yourtarget">
    your svg page
  </g>
</svg>

Hinweis : Skala 1.0 ist 100%

Gary Hayes
quelle
7
OK. Ich will JS nicht dabei haben. Gibt es eine Möglichkeit, es an die Eltern anzupassen?
bjb568
@bj setAttribute ist das gleiche wie <tag attribute = "value">
John Ktejik
17

Herumspielen & festgestellt, dass dieses CSS die SVG im Chrome-Browser bis zu dem Punkt enthält, an dem der Container größer als das Bild ist:

div.inserted-svg-logo svg { max-width:100%; }

Scheint auch in FF + IE 11 zu funktionieren.

Kerry7777
quelle
Dies löste das Problem für mich. Ich habe den Überlauf allerdings nur in iOS gesehen. Vielen Dank!
Evan Mattson
5
Mit beiden max-width: 100%und max-height: 100%wird die svg immer auf den Behälter , ohne jemals zu überfüllt oder zu verlieren , das Seitenverhältnis skaliert werden.
Gavin
2
@ Gavin max-height: 100%funktioniert nicht für mich, gelöst mit vhanstelle von%
Pavel
2

Das Ändern der SVG-Datei war für mich keine faire Lösung. Stattdessen habe ich relative CSS-Einheiten verwendet .

vh, vw, %Sind sehr praktisch. Ich habe ein CSS verwendet height: 2.4vh;, um eine dynamische Größe für meine SVG-Bilder festzulegen.

canbax
quelle
1

Ein anderer einfacher Weg ist

transform: scale(1.5);
Kasim ŞEN
quelle
0

Das Anpassen des Attributs currentScale funktioniert im IE (ich habe mit IE 11 getestet), jedoch nicht in Chrome.

Fabian Madurai
quelle