¿Cómo puedo hacer una escala svg con su contenedor principal?

236

Quiero tener una escala de contenido del elemento svg en línea cuando el tamaño no es nativo. Por supuesto, podría tenerlo como un archivo separado y escalarlo así.

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

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

Sin embargo, quiero agregar estilos adicionales al SVG a través de CSS, por lo que vincular uno externo no es una opción. ¿Cómo hago una escala SVG en línea?

bjb568
fuente
2
pruebe los precedentes en anchos y alturas de svg.
ncm
@ncm ¿Cómo se haría con JS?
Mawg dice que reinstale a Mónica el

Respuestas:

458

Para especificar las coordenadas dentro de la imagen SVG independientemente del tamaño escalado de la imagen, use el viewBoxatributo en el elemento SVG para definir cuál es el cuadro delimitador de la imagen en el sistema de coordenadas de la imagen, y use los atributos widthy heightpara definir qué el ancho o alto son con respecto a la página que lo contiene.

Por ejemplo, si tiene lo siguiente:

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

Se representará como un triángulo de 10 px por 20 px:

Triángulo 10x20

Ahora, si establece solo el ancho y la altura, eso cambiará el tamaño del elemento SVG, pero no escalará el triángulo:

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

Triángulo 10x20

Si configura el cuadro de vista, eso hace que se transforme la imagen de modo que el cuadro dado (en el sistema de coordenadas de la imagen) se amplíe para ajustarse al ancho y alto dados (en el sistema de coordenadas de la página). Por ejemplo, para escalar el triángulo para que sea 100 px por 50 px:

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

Triángulo 100x50

Si desea escalarlo al ancho de la ventana HTML:

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

Triángulo 300x150

Tenga en cuenta que, por defecto, la relación de aspecto se conserva. Entonces, si especifica que el elemento debe tener un ancho del 100%, pero una altura de 50px, en realidad solo se escalará hasta la altura de 50px (a menos que tenga una ventana muy estrecha):

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

Triángulo 100x50

Si realmente desea que se estire horizontalmente, desactive la preservación de la relación de aspecto con 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>

Triángulo 300x50

(tenga en cuenta que, mientras que en mis ejemplos utilizo la sintaxis que funciona para la incrustación de HTML, para incluir los ejemplos como una imagen en StackOverflow, en lugar de eso estoy incrustando en otro SVG, así que necesito usar una sintaxis XML válida)

Brian Campbell
fuente
1
¿Cómo se hace no solo el viewBox preserveAspectRatio, sino también el cuadro principal? Quiero ancho: 100%; altura: auto para ello.
bjb568
1
@ Amigo: Creo que el ejemplo con width="100%"y sin altura especificada hace lo que quieres. He agregado imágenes para demostrar. Tiene 100% de ancho y aumenta la altura proporcionalmente. Si eso no es lo que estás buscando, ¿puedes tratar de aclarar lo que quieres decir?
Brian Campbell
1
Oh. No hay problema en realidad. Es solo un error de webkit. En Safari y Chrome, la altura "real" es 100% por defecto, no automática. ¿Cómo podría evitar esto entonces?
bjb568
44
@ Amigo Ah, sí, ya veo. Funciona bien en Firefox, pero no en Chrome o Safari. De acuerdo con la especificación SVG , Firefox parece ser correcto; mientras que el valor predeterminado de widthy heightpara un elemento SVG es 100%, esta no es la definición CSS del 100% (100% del bloque que contiene), sino el 100% de la ventana gráfica que se ha especificado en función de la relación de aspecto intrínseca ( que se calcula a partir de viewBoxcuando se da eso). Todavía no he encontrado una solución para ese problema que funcione en Chrome / Safari.
Brian Campbell
1
Esto funciona para mi. Primero creo un atributo viewBox en el elemento SVG y establezco el valor en "0 0 [ancho de svg original] [altura de svg original]". A continuación, cambio el atributo de ancho del elemento SVG a "auto" y el atributo de altura a "100%". El contenedor también debe tener una altura definida. Esto escala el vector al 100% de la altura del contenedor, permitiendo que el ancho flote. Finalmente, configure el ancho máximo de CSS del SVG en 100% para evitar sobrepasar el contenedor.
Ryan Griggs
28

Después de 48 horas de investigación, terminé haciendo esto para obtener una escala proporcional:

NOTA: Esta muestra está escrita con React. Si no está utilizando eso, cambiar la parte posterior cosas caso camello guiones (es decir: el cambio backgroundColora background-colory cambiar el estilo Objectde nuevo a una 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>

Esto es lo que está sucediendo en el código de muestra anterior:

CAJA DE VISTA

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

min-x, min-y, ancho y alto

es decir: viewbox = "0 0 1000 1000"

Viewbox es un atributo importante porque básicamente le dice al SVG qué tamaño dibujar y dónde. Si utilizó CSS ​​para hacer el SVG 1000x1000 px pero su cuadro de vista era 2000x2000, vería el cuarto superior izquierdo de su SVG.

Los primeros dos números, min-x y min-y, determinan si el SVG debe compensarse dentro del cuadro de vista.

Mi SVG necesita moverse arriba / abajo o izquierda / derecha

Examine esto: viewbox = "50 50 450 450"

Los primeros dos números desplazarán su SVG hacia la izquierda 50px y hacia arriba 50px, y los segundos dos números son el tamaño del cuadro de vista: 450x450 px. Si su SVG es 500x500 pero tiene algo de relleno adicional, puede manipular esos números para moverlo dentro del "cuadro de vista".

Su objetivo en este punto es cambiar uno de esos números y ver qué sucede.

También puede omitir por completo el cuadro de vista, pero luego su kilometraje variará dependiendo de cualquier otra configuración que tenga en ese momento. En mi experiencia, encontrará problemas para preservar la relación de aspecto porque el cuadro de vista ayuda a definir la relación de aspecto.

PRESERVAR LA RELACIÓN DE ASPECTO

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

Según mi investigación, hay muchas configuraciones de relación de aspecto diferentes, pero se llama a la predeterminada xMidYMid meet. Lo puse en el mío para recordarme explícitamente. xMidYMid meethace que se ajuste proporcionalmente en función del punto medio X e Y. Esto significa que permanece centrado en el cuadro de vista.

ANCHURA

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

Mira mi código de ejemplo arriba. Observe cómo configuro solo el ancho, no la altura. Lo configuré al 100% para que llene el contenedor en el que se encuentra. Esto es lo que probablemente más contribuye a responder esta pregunta de desbordamiento de pila.

Puede cambiarlo al valor de píxel que desee, pero recomendaría usar el 100% como lo hice para aumentarlo al máximo y luego controlarlo con CSS a través del contenedor principal. Recomiendo esto porque obtendrá el control "adecuado". Puede usar consultas de medios y puede controlar el tamaño sin JavaScript loco.

ESCALANDO CON CSS

Mira mi código de ejemplo arriba nuevamente. Observe cómo tengo estas propiedades:

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

Esto es adicional, pero le muestra cómo permitir que el usuario cambie el tamaño del SVG mientras mantiene la relación de aspecto adecuada. Debido a que el SVG mantiene su propia relación de aspecto, solo necesita hacer que el ancho sea redimensionable en el contenedor principal, y cambiará de tamaño según lo desee.

Dejamos solo la altura y / o la configuramos en auto, y controlamos el cambio de tamaño con el ancho. Elegí el ancho porque a menudo es más significativo debido a los diseños receptivos.

Aquí hay una imagen de estas configuraciones en uso:

ingrese la descripción de la imagen aquí

Si lees todas las soluciones en esta pregunta y aún estás confundido o no ves lo que necesitas, mira este enlace aquí. Lo encontré muy útil:

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

Es un artículo masivo, pero desglosa casi todas las formas posibles de manipular un SVG, con o sin CSS. Recomiendo leerlo mientras bebe un café de manera informal o elige líquidos seleccionados.

agm1984
fuente
Esto no parece funcionar para ningún SVG: si no tiene el control de la fuente SVG, este método falla cuando el SVG tiene un ancho fijo.
user48956
@ user48956 Siempre puede manipularlo después del hecho con JavaScript.
Andrew
Sí, siempre puede hurgar en las entrañas de varios formatos de archivo con una programación, pero es de esperar que haya un método que funcione para todo tipo de activos (por ejemplo, PNG) y no requiera programación de JavaScript.
user48956
21

Querrás hacer una transformación como tal:

con JavaScript:

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

Con CSS:

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

Envuelva su página SVG en una etiqueta de grupo como tal y apúntela para manipular toda la página:

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

Nota : la escala 1.0 es 100%

Gary Hayes
fuente
77
Okay. No quiero a JS en esto. ¿Hay alguna manera de que se transforme para adaptarse al padre?
bjb568
@bj setAttribute es lo mismo que <tag attribute = "value">
john ktejik
17

Jugueteando y encontré que este CSS parece contener el SVG en el navegador Chrome hasta el punto en que el contenedor es más grande que la imagen:

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

También parece estar funcionando en FF + IE 11.

Kerry7777
fuente
Esto resolvió el problema para mí. Sin embargo, solo estaba viendo el desbordamiento en iOS. ¡Gracias!
Evan Mattson el
55
Usar ambos max-width: 100%y max-height: 100%hará que el svg siempre se ajuste al contenedor sin desbordarse ni perder su relación de aspecto.
Gavin
2
@Gavin max-height: 100%no funciona para mí, resuelto usando en vhlugar de%
Pavel
2

cambiar el archivo SVG no fue una solución justa para mí, así que en su lugar, utilicé unidades de CSS relativas .

vh, vw, %Son muy útiles. Utilicé un CSS como height: 2.4vh;para establecer un tamaño dinámico para mis imágenes SVG.

Canbax
fuente
1

Otra forma simple es

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

El ajuste del atributo currentScale funciona en IE (lo probé con IE 11), pero no en Chrome.

Fabian Madurai
fuente