Comment puis-je créer une échelle svg avec son conteneur parent?

236

Je veux avoir l'échelle de contenu d'un élément svg en ligne lorsque la taille n'est pas native. Bien sûr, je pourrais l'avoir dans un fichier séparé et le mettre à l'échelle comme ça.

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

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

Cependant, je veux ajouter des styles supplémentaires au SVG via CSS, donc lier un externe n'est pas une option. Comment créer une échelle SVG en ligne?

bjb568
la source
2
essayez les précédents en largeurs et hauteurs svg.
ncm
@ncm Comment cela se ferait-il avec JS?
Mawg dit réintégrer Monica

Réponses:

458

Pour spécifier les coordonnées dans l'image SVG indépendamment de la taille mise à l'échelle de l'image, utilisez l' viewBoxattribut sur l'élément SVG pour définir ce qu'est le cadre de sélection de l'image dans le système de coordonnées de l'image, et utilisez les attributs widthet heightpour définir ce que la largeur ou la hauteur sont par rapport à la page contenant.

Par exemple, si vous disposez des éléments suivants:

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

Il restituera un triangle de 10px par 20px:

Triangle 10x20

Maintenant, si vous ne définissez que la largeur et la hauteur, cela changera la taille de l'élément SVG, mais pas l'échelle du triangle:

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

Triangle 10x20

Si vous définissez la zone de vue, cela entraîne la transformation de l'image de sorte que la zone donnée (dans le système de coordonnées de l'image) soit agrandie pour s'adapter à la largeur et à la hauteur données (dans le système de coordonnées de la page). Par exemple, pour augmenter la taille du triangle à 100 pixels par 50 pixels:

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

Triangle 100x50

Si vous souhaitez l'adapter à la largeur de la fenêtre HTML:

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

Triangle 300x150

Notez que par défaut, le rapport hauteur / largeur est conservé. Donc, si vous spécifiez que l'élément doit avoir une largeur de 100%, mais une hauteur de 50 pixels, il ne sera en fait mis à l'échelle qu'à la hauteur de 50 pixels (sauf si vous avez une fenêtre très étroite):

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

Triangle 100x50

Si vous souhaitez qu'il s'étire horizontalement, désactivez la conservation des proportions avec 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>

Triangle 300x50

(notez que même si dans mes exemples j'utilise une syntaxe qui fonctionne pour l'intégration HTML, pour inclure les exemples en tant qu'image dans StackOverflow, je suis plutôt intégré dans un autre SVG, donc je dois utiliser une syntaxe XML valide)

Brian Campbell
la source
1
Comment faites-vous non seulement la viewBox preserveAspectRatio, mais aussi la boîte principale? Je veux une largeur: 100%; hauteur: auto pour ça.
bjb568
1
@Dude: Je pense que l'exemple avec width="100%"et sans hauteur spécifiée fait ce que vous voulez. J'ai ajouté des images pour démontrer. Il a 100% de largeur et augmente la hauteur proportionnellement. Si ce n'est pas ce que vous recherchez, pouvez-vous essayer de clarifier ce que vous vouliez dire?
Brian Campbell
1
Oh. Pas de problème en fait. C'est juste un bug de webkit. Dans Safari et Chrome, la hauteur "réelle" est de 100% par défaut, pas automatique. Comment pourrais-je contourner cela alors?
bjb568
4
@ Mec Ah, oui, je vois. Cela fonctionne bien dans Firefox, mais pas dans Chrome ou Safari. Selon la spécification SVG , Firefox semble être correct; Bien que la valeur par défaut de widthet heightpour un élément SVG soit 100%, ce n'est pas la définition CSS de 100% (100% du bloc contenant), mais plutôt 100% de la fenêtre d'affichage qui a été spécifiée en fonction du rapport d'aspect intrinsèque ( qui est calculé à partir du viewBoxmoment où cela est donné). Je n'ai pas encore trouvé de solution à ce problème qui fonctionne dans Chrome / Safari.
Brian Campbell
1
Cela fonctionne pour moi. J'ai d'abord créé un attribut viewBox sur l'élément SVG et défini la valeur sur "0 0 [largeur de svg d'origine] [hauteur de svg d'origine]". Ensuite, je change l'attribut width de l'élément SVG en "auto" et l'attribut height en "100%". Le conteneur doit également avoir une hauteur définie. Cela redimensionne le vecteur à 100% de la hauteur du conteneur, permettant à la largeur de flotter. Enfin, définissez la largeur maximale CSS du SVG à 100% pour éviter de dépasser le conteneur.
Ryan Griggs
28

Après environ 48 heures de recherche, j'ai fini par le faire pour obtenir une mise à l'échelle proportionnelle:

REMARQUE: cet exemple est écrit avec React. Si vous ne l' utilisez que, changer les choses cas de dos de chameau à des traits d' union (ex: changement backgroundColorà background-colorchanger le style de Objectretour à un 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>

Voici ce qui se passe dans l'exemple de code ci-dessus:

VIEWBOX

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

min-x, min-y, largeur et hauteur

ie: viewbox = "0 0 1000 1000"

Viewbox est un attribut important car il indique essentiellement au SVG quelle taille dessiner et où. Si vous avez utilisé CSS pour créer le SVG 1000x1000 px mais que votre fenêtre d'affichage était 2000x2000, vous verriez le quart supérieur gauche de votre SVG.

Les deux premiers nombres, min-x et min-y, déterminent si le SVG doit être décalé à l'intérieur de la zone de visualisation.

Mon SVG doit être déplacé vers le haut / bas ou la gauche / droite

Examinez ceci: viewbox = "50 50 450 450"

Les deux premiers chiffres déplaceront votre SVG de 50px vers la gauche et de 50px vers le haut, et les deux deuxièmes nombres sont la taille de la fenêtre d'affichage: 450x450 px. Si votre SVG fait 500x500 mais qu'il a un rembourrage supplémentaire dessus, vous pouvez manipuler ces nombres pour le déplacer dans la "boîte de visualisation".

Votre objectif à ce stade est de modifier l'un de ces chiffres et de voir ce qui se passe.

Vous pouvez également omettre complètement la zone de visualisation, mais votre kilométrage variera en fonction de tous les autres paramètres que vous avez à l'époque. D'après mon expérience, vous rencontrerez des problèmes avec la préservation du rapport hauteur / largeur car la boîte de visualisation aide à définir le rapport hauteur / largeur.

CONSERVER LES PROPORTIONS

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

Sur la base de mes recherches, il existe de nombreux paramètres de rapport d'aspect différents, mais celui par défaut est appelé xMidYMid meet. Je l'ai mis sur le mien pour me le rappeler explicitement. xMidYMid meetle fait évoluer proportionnellement en fonction des points médians X et Y. Cela signifie qu'il reste centré dans la fenêtre d'affichage.

LARGEUR

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

Regardez mon exemple de code ci-dessus. Remarquez comment je règle uniquement la largeur, pas la hauteur. Je l'ai réglé à 100% pour qu'il remplisse le conteneur dans lequel il se trouve. C'est ce qui contribue probablement le plus à répondre à cette question de débordement de pile.

Vous pouvez le changer à la valeur de pixel que vous voulez, mais je recommanderais d'utiliser 100% comme je l'ai fait pour le gonfler jusqu'à la taille maximale, puis le contrôler avec CSS via le conteneur parent. Je le recommande car vous obtiendrez un contrôle "correct". Vous pouvez utiliser des requêtes multimédias et vous pouvez contrôler la taille sans JavaScript fou.

MISE À L'ÉCHELLE AVEC CSS

Regardez à nouveau mon exemple de code ci-dessus. Remarquez comment j'ai ces propriétés:

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

Ceci est supplémentaire, mais il vous montre comment permettre à l'utilisateur de redimensionner le SVG tout en conservant le bon rapport hauteur / largeur. Étant donné que le SVG conserve son propre rapport hauteur / largeur, il vous suffit de rendre la largeur redimensionnable sur le conteneur parent, et il sera redimensionné comme vous le souhaitez.

Nous laissons la hauteur seule et / ou la réglons sur auto, et nous contrôlons le redimensionnement avec la largeur. J'ai choisi la largeur car elle est souvent plus significative en raison des conceptions réactives.

Voici une image de ces paramètres utilisés:

entrez la description de l'image ici

Si vous avez lu toutes les solutions de cette question et êtes toujours confus ou ne voyez pas tout à fait ce dont vous avez besoin, consultez ce lien ici. Je l'ai trouvé très utile:

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

C'est un article massif, mais il décompose à peu près toutes les façons possibles de manipuler un SVG, avec ou sans CSS. Je vous recommande de le lire tout en buvant un café ou votre choix de liquides choisis.

agm1984
la source
Cela ne semble pas fonctionner pour n'importe quel SVG - Si vous n'avez pas le contrôle de la source SVG, cette méthode échoue lorsque le SVG a une largeur fixe.
user48956
@ user48956 Vous pouvez toujours le manipuler après coup avec JavaScript.
Andrew
Oui - vous pouvez toujours piquer les entrailles de divers formats de fichiers avec une programmation - mais vous espérez qu'il y aurait une méthode qui fonctionne pour toutes sortes d'actifs (par exemple PNG) et ne nécessite pas de programmation JavaScript.
user48956
21

Vous voudrez faire une transformation en tant que telle:

avec JavaScript:

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

Avec CSS:

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

Enveloppez votre page SVG dans une balise de groupe en tant que telle et ciblez-la pour manipuler la page entière:

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

Remarque : l'échelle 1.0 est 100%

Gary Hayes
la source
7
D'accord. Je ne veux pas de JS là-dedans. Existe-t-il un moyen de le transformer pour l'adapter au parent?
bjb568
@bj setAttribute est la même chose que <tag attribute = "value">
john ktejik
17

Déconner et trouvé que ce CSS semble contenir le SVG dans le navigateur Chrome jusqu'au point où le conteneur est plus grand que l'image:

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

Semble également fonctionner dans FF + IE 11.

Kerry7777
la source
Cela a résolu le problème pour moi. Cependant, je ne voyais que le débordement dans iOS. Merci!
Evan Mattson
5
L'utilisation des deux max-width: 100%et max-height: 100%rendra le svg toujours à l'échelle du conteneur sans jamais déborder ni perdre son rapport hauteur / largeur.
Gavin
2
@Gavin max-height: 100%ne fonctionne pas pour moi, résolu en utilisant vhau lieu de%
Pavel
2

changer le fichier SVG n'était pas une solution équitable pour moi, alors j'ai plutôt utilisé des unités CSS relatives .

vh, vw, %Sont très pratiques. J'ai utilisé un CSS comme height: 2.4vh;pour définir une taille dynamique pour mes images SVG.

canbax
la source
1

Un autre moyen simple est

transform: scale(1.5);
Kasim ŞEN
la source
0

L'ajustement de l'attribut currentScale fonctionne dans IE (j'ai testé avec IE 11), mais pas dans Chrome.

Fabian Madurai
la source