Comment redimensionner les images proportionnellement / garder le rapport hauteur / largeur?

167

J'ai des images qui seront assez grandes en dimension et je veux les réduire avec jQuery tout en gardant les proportions contraintes, c'est-à-dire le même rapport hauteur / largeur.

Quelqu'un peut-il m'indiquer du code ou expliquer la logique?

Kobe
la source
4
Pouvez-vous expliquer pourquoi jQuery doit être utilisé? Il existe une solution CSS uniquement (voir ma réponse ): définissez son max-widthet max-heightsur 100%.
Dan Dascalescu
9
Juste au cas où quelqu'un ne le saurait pas, si vous ne définissez qu'une seule dimension de l'image (largeur ou hauteur), elle est redimensionnée proportionnellement. C'est comme ça depuis l'aube du Web. Par exemple:<img src='image.jpg' width=200>
GetFree
2
En outre, vous pouvez envisager d'utiliser quelque chose comme slimmage.js pour économiser la bande passante et la RAM de l'appareil mobile.
Lilith River

Réponses:

188

Jetez un œil à ce morceau de code sur 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
la source
1
Désolé, il manque une logique mathématicienne… que se passe-t-il lorsque vous devez tout augmenter (disons, vous augmentez maxHeight)?
Ben
4
Cela peut-il être fait uniquement avec CSS? (max-width, height: auto, etc?)
Tronathan
11
Je ne sais pas pourquoi jQuery est nécessaire pour cela. Réduire l'image proportionnellement sur le client peut être fait avec CSS, et c'est trivial: il suffit de définir son max-widthet max-heightsur 100%. jsfiddle.net/9EQ5c
Dan Dascalescu
10
Cela ne peut pas être fait avec CSS à cause de la déclaration IF. Je pense que le but est de remplir l'image miniature. Si l'image est trop grande, elle doit avoir une largeur maximale, si l'image est trop large, elle doit être une hauteur maximale. Si vous utilisez CSS max-width, max-height, vous obtiendrez des miniatures avec des espaces au lieu d'être entièrement remplies
ntgCleaner
Ce code peut-il causer des problèmes dans les navigateurs, se bloquer ou ralentir?
Déjà Bond
445

Je pense que c'est une méthode vraiment cool :

 /**
  * 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
la source
33
Réponse largement supérieure! La bonne réponse tombe à plat sur son visage si la hauteur ET la largeur sont toutes deux plus grandes. Vraiment, bien, aussi belle moustache.
Starkers
1
Vous avez raison à propos de @sstauross, les pixels décimaux peuvent avoir des résultats légèrement inattendus . Dans mon cas d'utilisation cependant, c'était négligeable. Je suppose Math.floorque cela aidera vraiment avec un design pixel parfait :-)
Jason
1
Merci, j'avais besoin de ce presque "one-liner".
Hernán
1
Merci Jason, cette réponse m'a vraiment aidé.
Ashok Shah
4
C'est une manière fantastique de gérer ce problème! Je l'ai un peu modifié pour les éléments img + empêcher l'agrandissement de l'image: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 je comprends bien la question, vous n'avez même pas besoin de jQuery pour cela. Réduire l'image proportionnellement sur le client peut être fait avec CSS seul: il suffit de définir son max-widthet max-heightsur 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>​

Voici le violon: http://jsfiddle.net/9EQ5c/

Dan Dascalescu
la source
2
C'est une réponse beaucoup plus facile que ci-dessus. Merci. btw comment avez-vous obtenu le lien "ma réponse" pour faire défiler jusqu'à votre message?
SnareChops
@SnareChops: c'est simplement une ancre HTML .
Dan Dascalescu
1
@SnareChops: si vous utilisez le lien donné par le lien «partager» sous la réponse, il fera également défiler jusqu'à la réponse.
Flimm
1
@Flimm Parce que les travées ne sont pas affichées: bloquer par défaut. Ajoutez simplement display: block ou faites-en un div.
mahemoff
1
Dans mon cas, l'IMG a été rendu avec WordPress, donc la largeur et la hauteur du chapeau sont définies. En CSS, j'ai également dû définir width: auto; height: auto;pour que votre code fonctionne :)
lippoliv
12

Afin de déterminer le rapport hauteur / largeur , vous devez avoir un rapport à viser.

la taille

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

Largeur

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

Dans cet exemple, j'utilise 16:10depuis le format d'image typique du moniteur.

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

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

Les résultats ci-dessus seraient 147et300

Meule
la source
Considérant que 300 = largeur diagonale = hauteur * le rapport et la hauteur sont les mêmes que vous l'avez dit
Johny Pie
6

en fait, je viens de rencontrer ce problème et la solution que j'ai trouvée était étrangement simple et étrange

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

et miraculeusement l'image est redimensionnée à la nouvelle hauteur et en conservant le même rapport!

WindowsMaker
la source
1
Je pense que c'est utile - mais je suppose que cela ne contraindra pas l'image si elle est très très large, par exemple, à une largeur maximale ...
stephendwolff
Ce truc fonctionne lorsque vous ne définissez pas l'autre attribut. (largeur dans ce cas)
NoobishPro
4

Il y a 4 paramètres à ce problème

  1. largeur d'image actuelle iX
  2. hauteur actuelle de l'image iY
  3. largeur de la fenêtre cible cX
  4. hauteur cible de la fenêtre cY

Et il y a 3 paramètres conditionnels différents

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

Solution

  1. Trouvez le petit côté du port de vue cible F
  2. Trouvez le plus grand côté du port de vue actuel L
  3. Trouvez le facteur des deux F / L = facteur
  4. Multipliez les deux côtés du port actuel avec le facteur, c'est-à-dire fX = iX * factor; fY = iY * facteur

c'est tout ce que vous devez faire.

//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 ; 

C'est un forum mature, je ne vous donne pas de code pour ça :)

PRASANTH KOLLAIKAL
la source
2
Publier la méthode derrière cela est génial, mais je vous note de ne pas vraiment aider l'utilisateur en publiant du code. Semble un peu obstructif
Doidgey
6
"Quelqu'un peut-il me diriger vers un code ou expliquer la logique?" - De toute évidence, il était d'accord pour que seule la méthode lui soit expliquée. Personnellement, je pense que ce serait la meilleure façon d'aider quelqu'un, de l'aider à comprendre les méthodes plutôt que de lui faire copier et coller du code.
JessMcintosh
@JessMcintosh, dommage que le bazillion de modifications apportées à la question d'origine ait rendu votre commentaire hors contexte :)
Jason J. Nathan
4

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

Le navigateur veillera à conserver le rapport hauteur / largeur intact.

c'est-à-dire entre max-widthen action lorsque la largeur de l'image est supérieure à la hauteur et que sa hauteur sera calculée proportionnellement. De même max-heightsera en vigueur lorsque la hauteur est supérieure à la largeur.

Vous n'avez pas besoin de jQuery ou de javascript pour cela.

Pris en charge par ie7 + et d'autres navigateurs ( http://caniuse.com/minmaxwh ).

sojin
la source
Bon conseil! Il suffit de mettre le CSS dans un fichier CSS et non directement dans le code html.
Mark du
Je pense que le problème avec cela est que cela ne fonctionnera pas si vous ne savez pas quelle est la largeur maximale et la hauteur maximale jusqu'au chargement de la page. C'est pourquoi une solution JS est nécessaire. C'est normalement le cas pour les sites réactifs.
Jason
2

Cela devrait fonctionner pour les images avec toutes les proportions possibles

$(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
la source
2

Voici une correction à la réponse de Mehdiway. La nouvelle largeur et / ou hauteur n'étaient pas définies sur la valeur maximale. Un bon cas de test est le suivant (1768 x 1075 pixels): http://spacecoastsports.com/wp-content/uploads/2014/06/sportsballs1.png . (Je n'ai pas pu le commenter ci-dessus en raison du manque de points de réputation.)

  // 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
la source
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
la source
5
Pensez à ajouter une explication, pas seulement un code lorsque vous répondez à un message.
Jørgen R
1

Si l'image est proportionnée, ce code remplira le wrapper avec l'image. Si l'image n'est pas proportionnée, la largeur / hauteur supplémentaire sera rognée.

    <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
la source
1

Sans temp-vars ou parenthèses supplémentaires.

    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;
      }

Gardez à l'esprit: les moteurs de recherche ne l'aiment pas, si l'attribut largeur et hauteur ne correspond pas à l'image, mais ils ne connaissent pas JS.

BF
la source
1

Après quelques essais et erreurs, je suis arrivé à cette solution:

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
la source
1

Le redimensionnement peut être réalisé (en maintenant le rapport hauteur / largeur) en utilisant CSS. Il s'agit d'une autre réponse simplifiée inspirée du post 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"/>

rush dee
la source
1

2 étapes:

Étape 1) Calculez le rapport largeur / hauteur d'origine de l'image.

Étape 2) Multipliez le rapport largeur_original / hauteur_original par la nouvelle hauteur souhaitée pour obtenir la nouvelle largeur correspondant à la nouvelle hauteur.

Hitesh Ranaut
la source
0

Ce problème peut être résolu par CSS.

.image{
 max-width:*px;
}
Ravinder de Banoth
la source
0

Redimensionner pour s'adapter au conteneur, obtenir le facteur d'échelle, réduire le pourcentage de contrôle

 $(function () {
            let ParentHeight = 200;
            let ParentWidth = 300;
            $("#Parent").width(ParentWidth).height(ParentHeight);
            $("#ParentHeight").html(ParentHeight);
            $("#ParentWidth").html(ParentWidth);

            var RatioOfParent = ParentHeight / ParentWidth;
            $("#ParentAspectRatio").html(RatioOfParent);

            let ChildHeight = 2000;
            let ChildWidth = 4000;
            var RatioOfChild = ChildHeight / ChildWidth;
            $("#ChildAspectRatio").html(RatioOfChild);

            let ScaleHeight = ParentHeight / ChildHeight;
            let ScaleWidth = ParentWidth / ChildWidth;
            let Scale = Math.min(ScaleHeight, ScaleWidth);

            $("#ScaleFactor").html(Scale);
            // old scale
            //ChildHeight = ChildHeight * Scale;
            //ChildWidth = ChildWidth * Scale;

            // reduce scale by 10%, you can change the percentage
            let ScaleDownPercentage = 10;
            let CalculatedScaleValue = Scale * (ScaleDownPercentage / 100);
            $("#CalculatedScaleValue").html(CalculatedScaleValue);

            // new scale
            let NewScale = (Scale - CalculatedScaleValue);
            ChildHeight = ChildHeight * NewScale;
            ChildWidth = ChildWidth * NewScale;

            $("#Child").width(ChildWidth).height(ChildHeight);
            $("#ChildHeight").html(ChildHeight);
            $("#ChildWidth").html(ChildWidth);

        });
        #Parent {
            background-color: grey;
        }

        #Child {
            background-color: red;
        }
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Parent">
    <div id="Child"></div>
</div>

<table>
    <tr>
        <td>Parent Aspect Ratio</td>
        <td id="ParentAspectRatio"></td>
    </tr>
    <tr>
        <td>Child Aspect Ratio</td>
        <td id="ChildAspectRatio"></td>
    </tr>
    <tr>
        <td>Scale Factor</td>
        <td id="ScaleFactor"></td>
    </tr>
    <tr>
        <td>Calculated Scale Value</td>
        <td id="CalculatedScaleValue"></td>
    </tr>
    <tr>
        <td>Parent Height</td>
        <td id="ParentHeight"></td>
    </tr>
    <tr>
        <td>Parent Width</td>
        <td id="ParentWidth"></td>
    </tr>
    <tr>
        <td>Child Height</td>
        <td id="ChildHeight"></td>
    </tr>
    <tr>
        <td>Child Width</td>
        <td id="ChildWidth"></td>
    </tr>
</table>

Arun Prasad ES
la source
-4

Cela a totalement fonctionné pour moi pour un élément déplaçable - aspectRatio: true

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