div 요소의 크기 조정


80

jQuery에는 resize()-이벤트가 있지만 창에서만 작동합니다.

jQuery(window).resize(function() { /* What ever */ });

이것은 잘 작동합니다! 하지만 이벤트를 div 요소에 추가하고 싶을 때 작동하지 않습니다.

예

jQuery('div').resize(function() { /* What ever */ });

div 요소의 크기가 변경되면 콜백을 시작하고 싶습니다. 크기 조정 가능한 이벤트를 시작하고 싶지 않습니다. div 요소의 크기가 변경되었는지 확인하는 이벤트입니다.

이를위한 해결책이 있습니까?


2
크기 조정 이벤트는 창 개체 (및 iframe 일 수 있음)에서만 발생합니다.
— BiAiB


도움이 될 수 있습니다 : resizeObserver. developer.mozilla.org/en-US/docs/Web/API/ResizeObserver . Chrome 64, Firefox 69 지원 ...
— captain puget

답변:


35

DIVresize이벤트를 발생시키지 않으므로 코딩 한 작업을 정확히 수행 할 수는 없지만 DOM 속성 모니터링을 살펴볼 수 있습니다 .

실제로 크기 조정과 같은 작업을하고 있고 이것이 div의 크기를 변경하는 유일한 방법 인 경우 크기 조정 플러그인은 자체 콜백을 구현할 것입니다.


$ (window) .trigger ( "resize");를 사용하여 창 크기 조정 이벤트를 트리거 할 수 있습니다.
— Laurent

32

요소의 너비가 변경되었을 때만 트리거에 관심이 있었기 때문에 (높이는 신경 쓰지 않습니다), 보이지 않는 iframe 요소를 사용하여 정확히 수행하는 jquery 이벤트를 만들었습니다.

$.event.special.widthChanged = {
  remove: function() {
      $(this).children('iframe.width-changed').remove();
  },
  add: function () {
      var elm = $(this);
      var iframe = elm.children('iframe.width-changed');
      if (!iframe.length) {
          iframe = $('<iframe/>').addClass('width-changed').prependTo(this);
      }
      var oldWidth = elm.width();
      function elmResized() {
          var width = elm.width();
          if (oldWidth != width) {
              elm.trigger('widthChanged', [width, oldWidth]);
              oldWidth = width;
          }
      }

      var timer = 0;
      var ielm = iframe[0];
      (ielm.contentWindow || ielm).onresize = function() {
          clearTimeout(timer);
          timer = setTimeout(elmResized, 20);
      };
  }
}

다음 CSS가 필요합니다.

iframe.width-changed {
    width: 100%;
    display: block;
    border: 0;
    height: 0;
    margin: 0;
}

당신은 행동 여기에서 볼 수 있습니다 widthChanged 바이올린


이것이 정답입니다. 이벤트를 iframe의 창에 연결하는 것은 간격보다 훨씬 적습니다.
— Kevin Beal 2014 년

1
이것은 완벽 해요! 난 내 완전히 동적으로 스타일 시트를 추가하여 기반 JS했다 : var ss = document.createElement('style'); ss.type = "text/css"; ss.innerHTML = "iframe.width-changed {width: 100%;display: block;border: 0;height: 0;margin: 0;}"; document.body.appendChild(ss);
— sroskelley

이것은 순수한 천재입니다.
— Thomas

사용하려고하는데 타이머와 setTimeout의 역할은 무엇입니까? 사용자가 요소의 크기를 조정할 때 감지하기에는 너무 많은 크기 조정을 방지하는 "디 바운스"/ 스로틀과 같은가요?
— Mathieu

네, 그것은 너무 많이에게 "widthChanged"트리거 호출 방지하는 것입니다
— 파 노스 Theof

22
// this is a Jquery plugin function that fires an event when the size of an element is changed
// usage: $().sizeChanged(function(){})

(function ($) {

$.fn.sizeChanged = function (handleFunction) {
    var element = this;
    var lastWidth = element.width();
    var lastHeight = element.height();

    setInterval(function () {
        if (lastWidth === element.width()&&lastHeight === element.height())
            return;
        if (typeof (handleFunction) == 'function') {
            handleFunction({ width: lastWidth, height: lastHeight },
                           { width: element.width(), height: element.height() });
            lastWidth = element.width();
            lastHeight = element.height();
        }
    }, 100);


    return element;
};

}(jQuery));

7

jquery 플러그인 jquery.resize를 만들었습니다. 지원되는 경우 resizeObserver 를 사용하거나 marcj / css-element-queries 스크롤 이벤트를 기반으로하는 솔루션 , setTimeout / setInterval이 없습니다.

당신은 단지

 jQuery('div').on('resize', function() { /* What ever */ });

또는 리사이 저 플러그인으로

jQuery('div').resizer(function() { /* What ever */ });

나는 jQuery 터미널을 위해 이것을 만들고 분리 된 repo 및 npm 패키지로 추출했지만 그 동안 요소가 iframe 내부에 있으면 크기 조정에 문제가 있었기 때문에 숨겨진 iframe으로 전환했습니다. 그에 따라 플러그인을 업데이트 할 수 있습니다. jQuery 터미널 소스 코드 에서 iframe 기반 크기 조정기 플러그인을 볼 수 있습니다 .

편집 : 페이지가 iframe 내부에있을 때 이전 솔루션이 작동하지 않았기 때문에 새 버전은 iframe을 사용하고 창 개체의 크기를 조정합니다.

EDIT2 : 대체가 iframe을 사용하기 때문에 양식 컨트롤이나 이미지와 함께 사용할 수 없으므로 래퍼 요소에 추가해야합니다.

EDIT3 : : 돌연변이 관찰자를 사용 하는 resizeObserver 폴리 필 을 사용하는 더 나은 솔루션 이 있습니다 (resizeObserver가 지원되지 않는 경우). IE에서도 작동합니다. 또한 TypeScript 타이핑도 있습니다.


좋은 생각이었습니다. 정말 잘 했어요.
— Marco Luzzara

6

이것에 대해 :

divH = divW = 0;
jQuery(document).ready(function(){
    divW = jQuery("div").width();
    divH = jQuery("div").height();
});
function checkResize(){
    var w = jQuery("div").width();
    var h = jQuery("div").height();
    if (w != divW || h != divH) {
        /*what ever*/
        divH = h;
        divW = w;
    }
}
jQuery(window).resize(checkResize);
var timer = setInterval(checkResize, 1000);

BTW div에 ID를 추가하고 $ ( "div")를 $ ( "# yourid")로 변경하면 더 빠르며 나중에 다른 div를 추가해도 깨지지 않습니다.


물론-그것은 단지 예일뿐입니다-물론 나는 내 요소를 선택하기 위해 id와 클래스를 사용합니다. 나는 당신의 아이디어가 마음에 듭니다 – 나는 그것이 효과가있을 것이라고 생각합니다! 감사합니다. 몇 분 안에 시도하고 피드백을 줄 것입니다.
— TJR

이것은 창의 resize이벤트가 발생할 때마다 크기 변경에 대해 DIV를 모니터링합니다 . div의 크기는 즉시 창 크기 조정없이 변경 될 수 있으며이 경우 /* what ever */부품이 평가되지 않습니다.
— David Hedlund 2012

권리! 그리고 이것이 제 프로젝트의 문제입니다. div 요소는 css 속성 Overflow : hidden이있는 외부 래퍼에 있으므로 창 크기가 변경되지 않습니다. 그러나 다른 방식으로 예제는 잘 작동합니다. 방금 테스트했습니다.
— TJR

@Timo : $(window).resize오른쪽 하단 모서리를 드래그하여 브라우저 창 크기를 물리적으로 조정하는 동작을 수신합니다. 이 이벤트를 트리거하는지 여부에 관계없이 DOM 이벤트가 overflow:hidden없습니다. 이 답변은 문제를 해결하지 않습니다. 트리거되지 않을 가능성이있는 임의의 이벤트 리스너에 연결하는 것보다 타이머에서이 코드를 실행하는 것이 더 합리적입니다. DOM 속성 모니터링을 사용하고 타이머로 대체 할 수 있다면 더 좋을 것입니다 (또는 div 크기가 변경 될 수있는 장소에서 일부 이벤트를 수동으로 발생).
— David Hedlund 2012

setInterval에 대한 코드를 추가했습니다. 1000ms는 너무 많을 수 있지만 너무 낮은 숫자는 CPU를 쉽게 죽일 수 있기 때문에 미세 조정이 필요합니다. 더 이상들을 필요가 없다는 것을 알고 있다면 clearInterval (timer)!
— Gavriel 2012

5

기본 JavaScript와 올해 출시 된 jQuery를위한 정말 멋지고 사용하기 쉽고 가벼운 (탐지에 네이티브 브라우저 이벤트 사용) 플러그인이 있습니다. 완벽하게 수행됩니다.

https://github.com/sdecima/javascript-detect-element-resize


1
당신은 지속적으로 폴링하지 않지만, 그것은 requestAnimationFrame을 사용 않는다고 말했다 : github.com/sdecima/javascript-detect-element-resize/blob/master/...
— 무하마드 Umer

1
흥미롭게도 참조 된 GitHub 프로젝트는이 블로그 게시물에서 영감을 얻었습니다 : backalleycoder.com/2013/03/18/… 그러나 게시물 의 코드는 나중에 크게 변경된 반면 GitHub 프로젝트는 이전 접근 방식을 사용하는 것으로 보입니다. 따라서 무엇을 사용할지 결정하기 전에 두 가지를 모두 살펴 보는 것이 좋습니다.
— CF


0

Google지도 통합의 경우 div의 크기가 변경되었을 때 감지하는 방법을 찾고있었습니다. Google지도는 항상 적절한 크기 (예 : 너비 및 높이)가 필요하기 때문에 올바르게 렌더링됩니다.

내가 생각해 낸 해결책은 이벤트의 위임, 내 경우에는 탭 클릭입니다. 이것은 물론 창 크기 조정이 될 수 있지만 아이디어는 동일하게 유지됩니다.

if (parent.is(':visible')) {
    w = parent.outerWidth(false);
    h = w * mapRatio /*9/16*/;
    this.map.css({ width: w, height: h });
} else {
    this.map.closest('.tab').one('click', function() {
        this.activate();
    }.bind(this));
}

this.map이 경우에는 내지도 div입니다. 부모님이로드시 보이지 않기 때문에 계산 된 너비와 높이가 0이거나 일치하지 않습니다. 를 사용 .bind(this)하여 스크립트 실행 ( this.activate)을 이벤트 ( click)에 위임 할 수 있습니다 .

이제 크기 조정 이벤트에도 동일하게 적용됩니다.

$(window).one('resize', function() {
    this.div.css({ /*whatever*/ });
}.bind(this));

누구에게나 도움이되기를 바랍니다!


0

이 기능을 시도하십시오 (div에서만 작동하지 않을 수 있습니다).

function resized(elem, func = function(){}, args = []){
    elem = jQuery(elem);
    func = func.bind(elem);
    var h = -1, w = -1;
    setInterval(function(){
        if (elem.height() != h || elem.width() != w){
            h = elem.height();
            w = elem.width();
            func.apply(null, args);
        }
    }, 100);
}

이렇게 사용할 수 있습니다

resized(/*element*/ '.advs-columns-main > div > div', /*callback*/ function(a){
    console.log(a);
    console.log(this); //for accessing the jQuery element you passed
}, /*callback arguments in array*/ ['I\'m the first arg named "a"!']);

업데이트 : 더 진보적 인 감시자를 사용할 수도 있습니다 (DOM 요소뿐만 아니라 모든 객체에 대해 작동 할 수 있음).

function changed(elem, propsToBeChanged, func = function(){}, args = [], interval = 100){
        func = func.bind(elem);
        var currentVal = {call: {}, std: {}};
        $.each(propsToBeChanged, (property, needCall)=>{
            needCall = needCall ? 'call' : 'std';
            currentVal[needCall][property] = new Boolean(); // is a minimal and unique value, its equivalent comparsion with each other will always return false
        });
        setInterval(function(){
            $.each(propsToBeChanged, (property, needCall)=>{
                try{
                    var currVal = needCall ? elem[property]() : elem[property];
                } catch (e){ // elem[property] is not a function anymore
                    var currVal = elem[property];
                    needCall = false;
                    propsToBeChanged[property] = false;
                }
                needCall = needCall ? 'call' : 'std';
                if (currVal !== currentVal[needCall][property]){
                    currentVal[needCall][property] = currVal;
                    func.apply(null, args);
                }
            });
        }, interval);
    }

먹어봐:

var b = '2',
    a = {foo: 'bar', ext: ()=>{return b}};
changed(a, {
// prop name || do eval like a function?
    foo:        false,
    ext:        true
}, ()=>{console.log('changed')})

b, a.foo 또는 a.ext를 직접 변경할 때마다 '변경됨'으로 기록됩니다.


setInterval크기 조정을 계속 시도하기 때문에 꽤 비쌀 수 있습니다
— ton

@ton : 나는 당신이 완전히 옳지 않다고 생각합니다. 이는 크기를 조정하는 동안 요소의 크기를 조정하려는 경우에만 발생합니다. : / 아니면 성능이 걱정 되십니까? 최신 브라우저에서는 심지어 "무거운"사이트에 완벽하게 작동
— KaMeHb

. console.log전에 간단한 것을 추가하면 $.each매번 인쇄되는 것을 볼 수 있습니다 100ms.interval
— ton

@ton : 당신은 나를 잘못 이해했습니다. 어떻게 setInterval작동 하는지 잘 알고 있습니다 . "살아있는"전자 메일과 같습니다. 서버에 지속적으로 핑을 보냅니다. 알아요. 그리고 뭐? 공연? 위의 내 의견을 읽으십시오. 다른 것이 걱정 되십니까? 친구여, 저를 써주세요.
— KaMeHb

0

화면 크기에 따라 텍스트 또는 콘텐츠 또는 속성을 변경할 수 있습니다. HTML :

<p class="change">Frequently Asked Questions (FAQ)</p>
<p class="change">Frequently Asked Questions </p>

자바 스크립트 :

<script>
const changeText = document.querySelector('.change');
function resize() {
  if((window.innerWidth<500)&&(changeText.textContent="Frequently Asked Questions (FAQ)")){
    changeText.textContent="FAQ";
  } else {
    changeText.textContent="Frequently Asked Questions (FAQ)";
  }
}
window.onresize = resize;
</script>

-2

div 자체의 크기를 조정하려면 CSS 스타일로 지정해야합니다. 오버플로 를 추가 하고 속성의 크기를 조정해야합니다 .

아래는 내 코드 스 니펫입니다.

#div1 {
        width: 90%;
        height: 350px;
        padding: 10px;
        border: 1px solid #aaaaaa;
        overflow: auto;
        resize: both;
    }

<div id="div1">

</div>

이 답변은 원본 게시물에는 적용되지 않습니다. 여기서 광범위한 논의는 요소의 크기를 설정하는 것이 아니라 요소의 크기에 대한 변경을 수신하고 나중에 작업을 수행하는 것입니다.
— MarsAndBack
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.