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.