Как пропорционально изменить размер изображения / сохранить соотношение сторон?


167

У меня есть изображения, которые будут довольно большими по размеру, и я хочу уменьшить их с помощью jQuery, сохраняя пропорции, то есть те же пропорции.

Может кто-нибудь указать мне код или объяснить логику?


4
Можете ли вы объяснить, почему должен использоваться jQuery? Есть решение только для CSS (см. Мой ответ ): установите его max-widthи max-heightв 100%.
Дан Даскалеску

9
На тот случай, если кто-то не знает, если вы установите только одно измерение изображения (ширину или высоту), оно будет пропорционально изменено. Так было с рассвета Интернета. Например:<img src='image.jpg' width=200>
GetFree

2
Кроме того, вы можете использовать что-то вроде slimmage.js для экономии пропускной способности и оперативной памяти мобильных устройств.
Река Лилит

Ответы:


188

Посмотрите на этот кусок кода с 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
        }
    });
});

1
Извините, не хватает математической логики ... что происходит, когда вам нужно увеличить все это (скажем, вы увеличиваете maxHeight)?
Бен

4
Можно ли это сделать только с помощью CSS? (максимальная ширина, высота: авто и т. д.)
Тронатан

11
Не уверен, зачем для этого нужен jQuery. Сжимать изображение пропорционально на клиенте можно с помощью CSS, и это тривиально: просто установите его max-widthи max-heightна 100%. jsfiddle.net/9EQ5c
Дан Даскалеску

10
Это не может быть сделано с CSS из-за заявления IF. Я считаю, что дело в том, чтобы заполнить миниатюру изображения. Если изображение слишком высокое, оно должно быть максимальной ширины, если изображение слишком широкое, это должна быть максимальная высота. Если вы выполните CSS max-width, max-height, вы получите миниатюры с пробелами вместо полностью заполненных
ntgCleaner

Этот код может вызвать проблемы в браузерах, вылетает или замедляется ??
Дежа Бонд

445

Я думаю, что это действительно крутой метод :

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

33
Значительно лучший ответ! Правильный ответ не имеет смысла, если высота и ширина больше. Действительно, хорошо, тоже хорошие усы.
Старкерс

1
Вы правы в том, что @sstauross, десятичные пиксели могут иметь немного неожиданные результаты . В моем случае использования, однако, это было незначительным. Я полагаю, Math.floorэто действительно поможет с идеальным дизайном пикселей :-)
Джейсон Дж. Натан

1
Спасибо, мне нужно было это почти "одна строка".
Эрнан

1
Спасибо Джейсон, этот ответ действительно помог мне.
Ашок Шах

4
Это фантастический способ решения этой проблемы! Я немного подправил элементы img +, чтобы не допустить увеличения изображения: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

Если я правильно понимаю вопрос, вам даже не нужен jQuery для этого. Пропорциональное сжатие изображения на клиенте может быть выполнено только с помощью CSS: просто установите его max-widthи max-heightна 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>​

Вот скрипка: http://jsfiddle.net/9EQ5c/


2
Это гораздо более простой ответ, чем выше. Спасибо. Кстати, как вы получили ссылку "мой ответ", чтобы прокрутить вниз к вашему сообщению?
SnareChops

@SnareChops: это просто якорь HTML .
Дан Даскалеску

1
@SnareChops: если вы воспользуетесь ссылкой, указанной ссылкой «Поделиться» под ответом, он также перейдет к ответу.
Flimm

1
@Flimm Потому что диапазоны не отображаются: блокировать по умолчанию. Просто добавьте display: block или сделайте его div.
mahemoff

1
В моем случае IMG был визуализирован с помощью WordPress, поэтому он установил ширину и высоту. В CSS я также должен был установить, width: auto; height: auto;чтобы ваш код работал :)
lippoliv

12

Чтобы определить соотношение сторон , вам нужно иметь соотношение, к которому нужно стремиться.

Рост

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

Ширина

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

В этом примере я использую 16:10это типичное соотношение сторон монитора.

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

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

Результаты сверху будут 147и300


Учитывая, что 300 = ширина диагонали = высота * соотношение и высота такие же, как вы сказали,
Джонни Пай

6

на самом деле я только что столкнулся с этой проблемой, и решение, которое я нашел, было странно простым и странным

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

и чудесным образом изображение изменяется до новой высоты и сохраняет то же соотношение!


1
я думаю, что это полезно - но я полагаю, что оно не будет ограничивать изображение, если оно будет очень широким, например, до максимальной ширины ...
stephendwolff

Это работает, когда вы не устанавливаете другой атрибут. (ширина в данном случае)
NoobishPro

4

Есть 4 параметра для этой проблемы

  1. текущая ширина изображения iX
  2. текущая высота изображения iY
  3. целевая ширина области просмотра cX
  4. высота окна просмотра цели cY

И есть 3 разных условных параметра

  1. cX> cY?
  2. iX> cX?
  3. IY> CY?

решение

  1. Найдите меньшую сторону целевого порта просмотра F
  2. Найти большую сторону текущего вида порта L
  3. Найти коэффициент как F / L = фактор
  4. Умножьте обе стороны текущего порта на коэффициент, т. Е. FX = iX * factor; FY = IY * фактор

это все, что вам нужно сделать.

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

Это зрелый форум, я не даю вам код для этого :)


2
Публиковать метод, стоящий за этим, замечательно, но я отмечаю вас за то, что вы на самом деле не помогли пользователю, разместив код. Кажется немного препятствующим
Doidgey

6
«Может кто-нибудь указать мне какой-нибудь код или объяснить логику?» - Очевидно, он был в порядке, когда ему объясняли только метод. Лично я думаю, что это был бы лучший способ помочь кому-то, помочь им понять методы, а не копировать и вставлять код.
JessMcintosh

@JessMcintosh, жаль, что внесенные изменения в исходный вопрос позволили сделать ваш комментарий вне контекста :)
Джейсон Дж. Натан,

4

Имеет ли <img src="/path/to/pic.jpg" style="max-width:XXXpx; max-height:YYYpx;" > ?

Браузер позаботится о сохранении пропорций.

т.е. max-widthвключается, когда ширина изображения больше высоты и его высота будет рассчитываться пропорционально. так жеmax-height будет действовать, когда высота больше ширины.

Вам не нужно jQuery или javascript для этого.

Поддерживается ie7 + и другими браузерами ( http://caniuse.com/minmaxwh ).


Отличный совет! Просто поместил бы CSS в CSS-файл, а не непосредственно в HTML-код.
Марк

Я думаю, что проблема в том, что это не будет работать, если вы не знаете, какова максимальная ширина и максимальная высота, пока страница не загрузится. Именно поэтому необходимо решение JS. Обычно это относится к адаптивным сайтам.
Джейсон Дж. Натан

2

Это должно работать для изображений со всеми возможными пропорциями

$(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
        }
    });
});

2

Вот исправление к ответу Mehdiway. Новая ширина и / или высота не были установлены на максимальное значение. Хороший тестовый пример: (1768 x 1075 пикселей): http://spacecoastsports.com/wp-content/uploads/2014/06/sportsballs1.png . (Я не смог прокомментировать это выше из-за отсутствия очков репутации.)

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

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

5
Пожалуйста, рассмотрите возможность добавления объяснения, а не только кода при ответе на пост.
Jørgen R

1

Если изображение пропорционально, то этот код заполнит упаковку изображением. Если изображение не пропорционально, дополнительная ширина / высота будет обрезана.

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

1

Без дополнительных временных переменных или скобок.

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

Имейте в виду: поисковым системам это не нравится, если атрибуты width и height не соответствуют изображению, но они не знают JS.


1

После некоторых проб и ошибок я пришел к этому решению:

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

1

Изменение размера может быть достигнуто (поддержание соотношения сторон) с помощью CSS. Это еще один упрощенный ответ, вдохновленный постом Дэна Даскалеску.

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


1

2 шага:

Шаг 1) рассчитать соотношение исходной ширины / исходной высоты изображения.

Шаг 2) умножьте соотношение original_width / original_height на новую желаемую высоту, чтобы получить новую ширину, соответствующую новой высоте.



0

Изменить размер, чтобы соответствовать контейнеру, получить коэффициент масштабирования, уменьшить процент управления

 $(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>


-4

Это полностью сработало для меня для перетаскиваемого элемента - aspectRatio: true

.appendTo(divwrapper).resizable({
    aspectRatio: true,
    handles: 'se',
    stop: resizestop 
})
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.