¿Cómo cambiar el tamaño de las imágenes proporcionalmente / mantener la relación de aspecto?

167

Tengo imágenes que tendrán una dimensión bastante grande y quiero reducirlas con jQuery manteniendo las proporciones restringidas, es decir, la misma relación de aspecto.

¿Alguien puede señalarme algún código o explicar la lógica?

kobe
fuente
44
¿Puedes explicar por qué se debe usar jQuery? Hay una solución solo para CSS (vea mi respuesta ): establezca su max-widthy max-heighta 100%.
Dan Dascalescu
9
En caso de que alguien no lo sepa, si configura solo una dimensión de la imagen (ancho o alto), se redimensionará proporcionalmente. Ha sido así desde los albores de la web. Por ejemplo:<img src='image.jpg' width=200>
GetFree
2
Además, puede considerar usar algo como slimmage.js para ahorrar ancho de banda y RAM del dispositivo móvil.
Lilith River

Respuestas:

188

Eche un vistazo a este código en http://ericjuden.com/2009/07/jquery-image-resize/

$(document).ready(function() {
    $('.story-small img').each(function() {
        var maxWidth = 100; // Max width for the image
        var maxHeight = 100;    // Max height for the image
        var ratio = 0;  // Used for aspect ratio
        var width = $(this).width();    // Current image width
        var height = $(this).height();  // Current image height

        // Check if the current width is larger than the max
        if(width > maxWidth){
            ratio = maxWidth / width;   // get ratio for scaling image
            $(this).css("width", maxWidth); // Set new width
            $(this).css("height", height * ratio);  // Scale height based on ratio
            height = height * ratio;    // Reset height to match scaled image
            width = width * ratio;    // Reset width to match scaled image
        }

        // Check if current height is larger than max
        if(height > maxHeight){
            ratio = maxHeight / height; // get ratio for scaling image
            $(this).css("height", maxHeight);   // Set new height
            $(this).css("width", width * ratio);    // Scale width based on ratio
            width = width * ratio;    // Reset width to match scaled image
            height = height * ratio;    // Reset height to match scaled image
        }
    });
});
Moin Zaman
fuente
1
Lo sentimos, falta algo de lógica matemática ... ¿qué pasa cuando necesitas aumentarlo todo (digamos, estás aumentando maxHeight)?
Ben
44
¿Se puede hacer esto solo con CSS? (max-width, height: auto, etc?)
Tronathan
11
No estoy seguro de por qué se necesita jQuery para esto. La reducción de la imagen proporcionalmente en el cliente se puede hacer con CSS, y es trivial: solo configure su max-widthy max-heightpara 100%. jsfiddle.net/9EQ5c
Dan Dascalescu
10
Esto no se puede hacer con CSS debido a la DECLARACIÓN SI. Creo que el punto es completar la imagen en miniatura. Si la imagen es demasiado alta, debe tener un ancho máximo, si la imagen es demasiado ancha, debe tener una altura máxima. Si haces CSS max-width, max-height, obtendrás miniaturas con espacios en blanco en lugar de estar completamente llenas
ntgCleaner
¿Este código puede causar problemas en los navegadores, bloqueos o ralentizado?
Déjà Bond
442

Creo que este es un método realmente genial :

 /**
  * Conserve aspect ratio of the original region. Useful when shrinking/enlarging
  * images to fit into a certain area.
  *
  * @param {Number} srcWidth width of source image
  * @param {Number} srcHeight height of source image
  * @param {Number} maxWidth maximum available width
  * @param {Number} maxHeight maximum available height
  * @return {Object} { width, height }
  */
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {

    var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);

    return { width: srcWidth*ratio, height: srcHeight*ratio };
 }
Jason J. Nathan
fuente
33
¡Respuesta muy superior! La respuesta correcta cae de plano si la altura Y el ancho son mayores. Realmente, bien, también un buen bigote.
Starkers
1
Tienes razón sobre eso @sstauross, los píxeles decimales pueden tener resultados ligeramente inesperados . Sin embargo, en mi caso de uso, fue insignificante. Supongo Math.floorque realmente ayudará con un diseño perfecto de píxeles :-)
Jason J. Nathan
1
Gracias, necesitaba esta casi "una línea".
Hernán
1
Gracias Jason, esta respuesta realmente me ayudó.
Ashok Shah
44
¡Esta es una forma fantástica de manejar este problema! Lo ajusté un poco para img elements + evitar agrandar la imagen:function imgSizeFit(img, maxWidth, maxHeight){ var ratio = Math.min(1, maxWidth / img.naturalWidth, maxHeight / img.naturalHeight); img.style.width = img.naturalWidth * ratio + 'px'; img.style.height = img.naturalHeight * ratio + 'px'; }
oriadam
70

Si entiendo la pregunta correctamente, ni siquiera necesitas jQuery para esto. La reducción de la imagen proporcionalmente en el cliente se puede hacer solo con CSS: solo configure su max-widthy max-heighta 100%.

<div style="height: 100px">
<img src="http://www.getdigital.de/images/produkte/t4/t4_css_sucks2.jpg"
    style="max-height: 100%; max-width: 100%">
</div>​

Aquí está el violín: http://jsfiddle.net/9EQ5c/

Dan Dascalescu
fuente
2
Esta es una respuesta mucho más fácil que la anterior. Gracias. por cierto, ¿cómo obtuviste el enlace "mi respuesta" para desplazarte hacia abajo hasta tu publicación?
SnareChops
@SnareChops: es simplemente un ancla HTML .
Dan Dascalescu
1
@SnareChops: si usa el enlace proporcionado por el enlace "compartir" debajo de la respuesta, también se desplazará a la respuesta.
Flimm
1
@Flimm Debido a que los tramos no se muestran: bloquear de forma predeterminada. Simplemente agregue display: block o conviértalo en un div.
mahemoff
1
En mi caso, el IMG se renderizó con WordPress, por lo que se estableció el ancho y la altura. En CSS también tuve que configurar width: auto; height: auto;para que tu código se ejecutara :)
lippoliv
12

Para determinar la relación de aspecto , debe tener una relación a la que apuntar.

Altura

function getHeight(length, ratio) {
  var height = ((length)/(Math.sqrt((Math.pow(ratio, 2)+1))));
  return Math.round(height);
}

Anchura

function getWidth(length, ratio) {
  var width = ((length)/(Math.sqrt((1)/(Math.pow(ratio, 2)+1))));
  return Math.round(width);
}

En este ejemplo, utilizo 16:10ya que esta es la típica relación de aspecto del monitor.

var ratio = (16/10);
var height = getHeight(300,ratio);
var width = getWidth(height,ratio);

console.log(height);
console.log(width);

Los resultados de arriba serían 147y300

Almiar
fuente
Teniendo en cuenta, 300 = diagonal width = altura * relación y la altura es igual que usted ha dicho
Johny Pie
6

De hecho, acabo de encontrarme con este problema y la solución que encontré fue extrañamente simple y extraña

$("#someimage").css({height:<some new height>})

¡y milagrosamente la imagen cambia de tamaño a la nueva altura y conserva la misma proporción!

WindowsMaker
fuente
1
Creo que esto es útil - pero supongo que no limitará la imagen si decir muy, muy amplia, con un ancho máximo ...
stephendwolff
Esto funciona cuando no establece el otro atributo. (ancho en este caso)
NoobishPro
4

Hay 4 parámetros para este problema.

  1. ancho de imagen actual iX
  2. altura de imagen actual iY
  3. ancho de ventana objetivo cX
  4. altura de ventana objetivo cY

Y hay 3 parámetros condicionales diferentes

  1. cX> cY?
  2. iX> cX?
  3. iY> cY?

solución

  1. Encuentre el lado más pequeño del puerto de vista de destino F
  2. Encuentra el lado más grande del puerto de vista actual L
  3. Encuentre el factor de ambos F / L = factor
  4. Multiplique ambos lados del puerto actual con el factor, es decir, fX = iX * factor; factor fY = iY *

eso es todo lo que necesitas hacer.

//Pseudo code


iX;//current width of image in the client
iY;//current height of image in the client
cX;//configured width
cY;//configured height
fX;//final width
fY;//final height

1. check if iX,iY,cX,cY values are >0 and all values are not empty or not junk

2. lE = iX > iY ? iX: iY; //long edge

3. if ( cX < cY )
   then
4.      factor = cX/lE;     
   else
5.      factor = cY/lE;

6. fX = iX * factor ; fY = iY * factor ; 

Este es un foro maduro, no te estoy dando código para eso :)

PRASANTH KOLLAIKAL
fuente
2
Publicar el método detrás de esto es genial, pero lo rebajo por no ayudar realmente al usuario publicando código. Parece un poco obstructivo
Doidgey
66
"¿Alguien puede señalarme algún código o explicar la lógica?" - Claramente estaba de acuerdo con que solo le explicaran el método. Personalmente, creo que esta sería la mejor manera de ayudar a alguien, para ayudarlo a comprender los métodos en lugar de hacer que copie y pegue el código.
JessMcintosh
@JessMcintosh, lástima que el bazillion de ediciones de la pregunta original hiciera que tu comentario fuera de contexto :)
Jason J. Nathan
4

Hace <img src="/path/to/pic.jpg" style="max-width:XXXpx; max-height:YYYpx;" > ayuda?

El navegador se encargará de mantener intacta la relación de aspecto.

es decir, se max-widthactiva cuando el ancho de la imagen es mayor que la altura y su altura se calculará proporcionalmente. similarmax-height entrará en vigor cuando la altura sea mayor que el ancho.

No necesita ningún jQuery o javascript para esto.

Compatible con ie7 + y otros navegadores ( http://caniuse.com/minmaxwh ).

sojin
fuente
Gran consejo! Simplemente pondría el CSS en un archivo CSS y no directamente en el código html.
Marque el
Creo que el problema con esto es que no funcionará cuando no sepa cuál es el ancho máximo y la altura máxima hasta que se cargue la página. Es por eso que se necesita una solución JS. Este suele ser el caso de los sitios receptivos.
Jason J. Nathan
2

Esto debería funcionar para imágenes con todas las proporciones posibles

$(document).ready(function() {
    $('.list img').each(function() {
        var maxWidth = 100;
        var maxHeight = 100;
        var width = $(this).width();
        var height = $(this).height();
        var ratioW = maxWidth / width;  // Width ratio
        var ratioH = maxHeight / height;  // Height ratio

        // If height ratio is bigger then we need to scale height
        if(ratioH > ratioW){
            $(this).css("width", maxWidth);
            $(this).css("height", height * ratioW);  // Scale height according to width ratio
        }
        else{ // otherwise we scale width
            $(this).css("height", maxHeight);
            $(this).css("width", height * ratioH);  // according to height ratio
        }
    });
});
Ajjaah
fuente
2

Aquí hay una corrección a la respuesta de Mehdiway. El nuevo ancho y / o alto no se establecieron en el valor máximo. Un buen caso de prueba es el siguiente (1768 x 1075 píxeles): http://spacecoastsports.com/wp-content/uploads/2014/06/sportsballs1.png . (No pude comentarlo anteriormente debido a la falta de puntos de reputación).

  // Make sure image doesn't exceed 100x100 pixels
  // note: takes jQuery img object not HTML: so width is a function
  // not a property.
  function resize_image (image) {
      var maxWidth = 100;           // Max width for the image
      var maxHeight = 100;          // Max height for the image
      var ratio = 0;                // Used for aspect ratio

      // Get current dimensions
      var width = image.width()
      var height = image.height(); 
      console.log("dimensions: " + width + "x" + height);

      // If the current width is larger than the max, scale height
      // to ratio of max width to current and then set width to max.
      if (width > maxWidth) {
          console.log("Shrinking width (and scaling height)")
          ratio = maxWidth / width;
          height = height * ratio;
          width = maxWidth;
          image.css("width", width);
          image.css("height", height);
          console.log("new dimensions: " + width + "x" + height);
      }

      // If the current height is larger than the max, scale width
      // to ratio of max height to current and then set height to max.
      if (height > maxHeight) {
          console.log("Shrinking height (and scaling width)")
          ratio = maxHeight / height;
          width = width * ratio;
          height = maxHeight;
          image.css("width", width);
          image.css("height", height);
          console.log("new dimensions: " + width + "x" + height);
      }
  }
Tom O'Hara
fuente
2
$('#productThumb img').each(function() {
    var maxWidth = 140; // Max width for the image
    var maxHeight = 140;    // Max height for the image
    var ratio = 0;  // Used for aspect ratio
    var width = $(this).width();    // Current image width
    var height = $(this).height();  // Current image height
    // Check if the current width is larger than the max
    if(width > height){
        height = ( height / width ) * maxHeight;

    } else if(height > width){
        maxWidth = (width/height)* maxWidth;
    }
    $(this).css("width", maxWidth); // Set new width
    $(this).css("height", maxHeight);  // Scale height based on ratio
});
khalid khan
fuente
55
Considere agregar una explicación, no solo código al responder una publicación.
Jørgen R
1

Si la imagen es proporcionada, este código llenará el contenedor con la imagen. Si la imagen no está en proporción, se recortará el ancho / alto adicional.

    <script type="text/javascript">
        $(function(){
            $('#slider img').each(function(){
                var ReqWidth = 1000; // Max width for the image
                var ReqHeight = 300; // Max height for the image
                var width = $(this).width(); // Current image width
                var height = $(this).height(); // Current image height
                // Check if the current width is larger than the max
                if (width > height && height < ReqHeight) {

                    $(this).css("min-height", ReqHeight); // Set new height
                }
                else 
                    if (width > height && width < ReqWidth) {

                        $(this).css("min-width", ReqWidth); // Set new width
                    }
                    else 
                        if (width > height && width > ReqWidth) {

                            $(this).css("max-width", ReqWidth); // Set new width
                        }
                        else 
                            (height > width && width < ReqWidth)
                {

                    $(this).css("min-width", ReqWidth); // Set new width
                }
            });
        });
    </script>
Anu
fuente
1

Sin temp-vars ni soportes adicionales.

    var width= $(this).width(), height= $(this).height()
      , maxWidth=100, maxHeight= 100;

    if(width > maxWidth){
      height = Math.floor( maxWidth * height / width );
      width = maxWidth
      }
    if(height > maxHeight){
      width = Math.floor( maxHeight * width / height );
      height = maxHeight;
      }

Recuerde: a los motores de búsqueda no les gusta, si el atributo ancho y alto no se ajusta a la imagen, pero no conocen JS.

BF
fuente
1

Después de algunas pruebas y errores, llegué a esta solución:

function center(img) {
    var div = img.parentNode;
    var divW = parseInt(div.style.width);
    var divH = parseInt(div.style.height);
    var srcW = img.width;
    var srcH = img.height;
    var ratio = Math.min(divW/srcW, divH/srcH);
    var newW = img.width * ratio;
    var newH = img.height * ratio;
    img.style.width  = newW + "px";
    img.style.height = newH + "px";
    img.style.marginTop = (divH-newH)/2 + "px";
    img.style.marginLeft = (divW-newW)/2 + "px";
}
Roland Hentschel
fuente
1

El cambio de tamaño se puede lograr (manteniendo la relación de aspecto) usando CSS. Esta es una respuesta más simplificada inspirada en la publicación de Dan Dascalescu.

http://jsbin.com/viqare

img{
     max-width:200px;
 /*Or define max-height*/
  }
<img src="http://e1.365dm.com/13/07/4-3/20/alastair-cook-ashes-profile_2967773.jpg"  alt="Alastair Cook" />

<img src="http://e1.365dm.com/13/07/4-3/20/usman-khawaja-australia-profile_2974601.jpg" alt="Usman Khawaja"/>

prisa dee
fuente
1

2 pasos

Paso 1) calcule la proporción del ancho original / altura original de la imagen.

Paso 2) multiplique la relación original_width / original_height por la nueva altura deseada para obtener el nuevo ancho correspondiente a la nueva altura.

Hitesh Ranaut
fuente
0

Este problema puede resolverse mediante CSS.

.image{
 max-width:*px;
}
banoth ravinder
fuente
-4

Esto funcionó totalmente para mí para un elemento arrastrable - AspectRatio: true

.appendTo(divwrapper).resizable({
    aspectRatio: true,
    handles: 'se',
    stop: resizestop 
})
Catherine
fuente