Пропорционально измените размер iframe, чтобы он поместился в DIV, используя jQuery

У меня есть iframe видео внутри div, например:

<div class="media">
    <iframe>
</div>

Я динамически устанавливаю размер DIV при изменении размера окна.

Я хочу масштабировать iframe так, чтобы он помещался внутри div, сохраняя его соотношение сторон. Большая часть кода связана с масштабированием изображений, что проще.

Это то, что у меня есть до сих пор, но это не работает:

jQuery.fn.fitToParent = function()
{
    this.each(function()
    {
        var width  = jQuery(this).width();
        var height = jQuery(this).height();
        var parentWidth  = jQuery(this).parent().width();
        var parentHeight = jQuery(this).parent().height();

        if(width < parentWidth)
        {
            newWidth  = parentWidth;
            newHeight = newWidth/width*height;
        }
        else
        {
            newHeight = parentHeight;
            newWidth  = newHeight/height*width;
        }

        jQuery(this).css({
            'height'     :newHeight,
            'width'      :newWidth'
        });
    });
};

По сути, я пытаюсь воспроизвести размер, который «фоновый размер: содержит» для изображений в CSS, но для iframe в DIV.

Спасибо за помощь!


person Drew Baker    schedule 16.09.2013    source источник


Ответы (3)


Отмечены три проблемы:

  1. У вас есть ошибка (конечная цитата) в вашем примере:

    :newWidth'

  2. Вам нужно установить фактические атрибуты высоты и ширины iframe, а не стиль. Стилизация размера iframe не влияет:

    $(this).width(newWidth);
    $(this).height(newHeight);
    
  3. расчет соотношения сторон был неправильным (необходимо сравнить соотношения, чтобы увидеть, как они перекрываются). Без этого не все случаи перекрытия обслуживаются.

    var aspect = width/height;
    var parentAspect = parentWidth/parentHeight;
    if (aspect > parentAspect)
    {
        newWidth  = parentWidth;
        newHeight = newWidth / aspect;
    }
    else
    {
        newHeight = parentHeight;
        newWidth  = newHeight * aspect;
    }
    

Я также немного подчистил код, чтобы ускорить доступ к элементам. Каждый вызов jQuery(this) стоит циклов.

JSFiddle здесь: http://jsfiddle.net/TrueBlueAussie/ZJDkF/8/

Обновления:

В jsfiddle теперь есть примеры 4 различных сценариев перекрытия, и каждый сохраняет пропорции iframe. Я также добавил упомянутое вами изменение размера окна и динамически изменил размер первого div для демонстрации.

person Gone Coding    schedule 19.09.2013
comment
Это потрясающе, очень хорошо сделано. Я назначу награду, как только это позволит мне. - person Drew Baker; 19.09.2013
comment
Safari будет терять коэффициент при изменении размера из-за суммирования ошибок округления. Поэтому я сохранил соотношение сторон на дисплее, и они использовали это соотношение для всех будущих размеров: jsfiddle.net/ZJDkF/ 9 - person Drew Baker; 19.09.2013

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

Сделал его плагином на GitHub здесь: https://github.com/drewbaker/fitToParent< /сильный>

Вот плагин jQuery:

jQuery.fn.fitToParent = function (options) {

    this.each(function () {

        // Cache the resize element
        var $el = jQuery(this);

        // Get size parent (box to fit element in)
        var $box;
        if( $el.closest('.size-parent').length ) {
            $box = $el.closest('.size-parent');
        } else {
            $box = $el.parent();
        }

        // These are the defaults.
        var settings = jQuery.extend({  
                height_offset: 0,
                width_offset: 0,
                box_height: $box.height(),
                box_width: $box.width(),
        }, options );

        // Setup box and element widths
        var width = $el.width();
        var height = $el.height();
        var parentWidth = settings.box_width - settings.width_offset;
        var parentHeight = settings.box_height - settings.height_offset;

        // Maintin aspect ratio
        var aspect = width / height;
        var parentAspect = parentWidth / parentHeight;

        // Resize to fit box
        if (aspect > parentAspect) {
            newWidth = parentWidth;
            newHeight = (newWidth / aspect);
        } else {
            newHeight = parentHeight;
            newWidth = newHeight * aspect;
        }

        // Set new size of element
        $el.width(newWidth);
        $el.height(newHeight); 

    });
};

Итак, если у вас есть HTML этого:

<div id="wrapper">
    <iframe width="720" height="405" src="//player.vimeo.com/video/19223989"></iframe>
</div>

Самый простой способ вызвать плагин выглядит так:

jQuery('#wrapper iframe').fitToParent();

Но я часто устанавливаю #wrapper близко к высоте и ширине окна, например:

// Get window height and width
var winHeight = jQuery(window).height();
var winWidth = jQuery(window).width();

// Set wrapper height/width to that of window
jQuery('#wrapper').height(winHeight).width(winWidth);

// Size Iframe
jQuery('#wrapper iframe').fitToParent({
    height_offset: 100, // Put some space around the video
    width_offset: 100, // Put some space around the video
});

Вы также можете ввести пользовательский размер поля, чтобы он соответствовал элементу, например:

// Get window height and width
var winHeight = jQuery(window).height();
var winWidth = jQuery(window).width();

// Size element
jQuery('#wrapper iframe').fitToParent({
    height_offset: 100, // Put some space around the video
    width_offset: 100, // Put some space around the video
    box_height: winHeight, // Force use of this box size
    box_width: winWidth // Force use of this box size
});

Я также добавил возможность установить класс CSS «size-parent» для родительского элемента, и затем он будет использовать этот родительский элемент для размера поля. Полный пример этого:

// HTML like this
<div id="wrapper" class="size-parent">
    <div class="media">
        <iframe width="720" height="405" src="//player.vimeo.com/video/19223989"></iframe>
    </div>
</div>

// jQuery like this
jQuery('.media iframe').fitToParent();    

Если вы не установите .size-parent, он вернется к родительскому элементу. Если вы установите параметр box_height/box_width, то они явно переопределяют все.

Теперь, чтобы показать, насколько мощным это может быть, попробуйте это для правильного соотношения сторон по вертикали и горизонтали по центру iFrame!

// CSS like this
#wrapper {
    text-align: center;
    display: table-cell;
    vertical-align: middle;
}
#wrapper iframe {
    display: inline-block;
}

// HTML like this
<div id="wrapper" class="size-wrapper">
    <iframe width="720" height="405" src="//player.vimeo.com/video/19223989"></iframe>
</div>

// jQuery like this
// Get window height and width
var winHeight = jQuery(window).height();
var winWidth = jQuery(window).width();

// Size wrapper
jQuery('#wrapper').height( winHeight ).width( winWidth );

// Size element
jQuery('#wrapper iframe').fitToParent({
    height_offset: 200, // Put some space around the video
    width_offset: 200, // Put some space around the video
});

// Fit iFrame to wrapper
jQuery('#wrapper iframe').fitToParent();

В реальной жизни я оборачиваю jQuery в функцию, а затем вызываю эту функцию при изменении размера окна для действительно отзывчивых iFrames!

person Drew Baker    schedule 09.08.2014

здесь:

http://jsfiddle.net/fFTS8/

  <div id="test" style="width:300px;height:200px;background:red;"></div>
  <script src="js/vendor/jquery-1.10.2.min.js"></script>
  <script type="text/javascript">
     jQuery.fn.fitToParent = function()
     {
        var that = this;

        function rezise() {
           that.each(function()
           {
             var a = $(this).width();
             var b = $(this).height();
             var c = $(this).parent().width();
             var d = $(this).parent().height();

             var ab = a/b;
             var cd = c/b;

             var e, f = 0; // e - newWidth, f - newHeight

             if(ab > cd) {
                e = c;
                f = c*b/a;
             } else {
                e = a*d/b;
                f = d;
             }

             $(this).width(e);
             $(this).height(f);
           });
        }

        $(window).resize(function() {
           rezise();
        });
     };
     $('#test').fitToParent();

  </script>
person marverix    schedule 19.09.2013
comment
По словам спрашивающего, iframe предназначен для изменения размера родительского div. Это перевернутое и изменяет размер div на iframe JSFiddle. - person Gone Coding; 19.09.2013