Is there a event invoked when a block's width changes?

后端 未结 3 1084
没有蜡笔的小新
没有蜡笔的小新 2021-01-13 13:04

I want to call my code when the width of the block I listen to changes. How to?

onresize is invoked only when the size of the window changes.

相关标签:
3条回答
  • 2021-01-13 13:31

    An option can be to use ResizeObserver:

    Observes all width changes, wen when MutationObserver doesn't as in Useless Code's answer.

    Does not have much browser compatibility, however.

    JS:

    var foo = document.getElementById('foo');
    
    var observer = new window.ResizeObserver(entries => 
       console.log(entries[0].contentRect.width));
    
       observer.observe(foo);
    }
    

    Stackblitz in Angular

    0 讨论(0)
  • 2021-01-13 13:35

    There's no default event provided by browser when the width of your element is changing. However, just like @Leo mentioned, you can register and trigger your own event.

    There are 3 steps you have to:

    1. Register a custom event
    2. Bind your element with the custom event
    3. Trigger the event when you resize the element

    The sample code is here:

    HTML

    <body>
      <div class="square"></div>
    </body>
    

    JS

    $(function() {
      var $square = $('.square');
    
      // Register a custom event and bind an event handler on it
      $square.on('square.resize', function() {
        console.log('Square is resized!');
      });    
    
      // Trigger that event when you change the square size
      function resizeSquare() {
        $square.width($square.width() + 10);
        $square.height($square.height() + 10);
        $square.trigger('square.resize');
      }
    
      // Anytime you resize the square, it will trigger 'square.resize' event
      // In this example, I am using setInverval() to resize the square, but you could
      // change it into any ways you like
      setInterval(resizeSquare, 1000);
    
    });
    

    You may check here for CodePen Live Demo

    0 讨论(0)
  • 2021-01-13 13:51

    As you mentioned, there is no resize event for elements on the page, just for window.

    You can however use Mutation Observers to detect changes in an element:

    const foo = document.querySelector('#foo');
    
    let oldWidth =  window.getComputedStyle(foo).getPropertyValue('width');
    const observer = new MutationObserver(function(mutations) {
      mutations.forEach(mutation => {
        if (mutation.target === foo &&
          mutation.attributeName === 'style' &&
          oldWidth !== foo.style.width) {
            foo.textContent = 'Width changed from ' +
              oldWidth + ' to ' + foo.style.width;
            oldWidth = foo.style.width;
        }
      });
    });
    
    // configure the observer, just look for attribute changes:
    const config = {
      attributes: true
    };
    
    // start observing
    observer.observe(foo, config);
    
    // change the width after a second so we can detect it
    setTimeout(() => {
      foo.style.width = '150px';
    }, 1000);
    #foo {
      border: 2px solid #f30;
      width: 100px;
      height: 100px;
      transition: width 1s;
    }
    <div id="foo">foo</div>

    With a little more work you can create a function that will add a custom event to the element you want to detect width changes on:

    const addWidthChangeEvent = function(element) {
      let oldWidth =  window.getComputedStyle(element).getPropertyValue('width');
      const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
          if (mutation.target === element &&
            mutation.attributeName === 'style' &&
            oldWidth !== element.style.width) {
              oldWidth = element.style.width;
              element.dispatchEvent(new Event('widthChange'));
          }
        });
      });
    
      // configure the observer, just look for attribute changes:
      const config = {
        attributes: true
      };
    
      observer.observe(element, config);
    };
    
    const foo = document.getElementById('foo');
    
    // add the new widthChange event to foo
    addWidthChangeEvent(foo);
    
    // add a listener for the new event
    foo.addEventListener('widthChange', event => {
      foo.textContent = foo.style.width;
    }, false);
    
    
    const randomInt = (min, max) => {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    };
    
    // change the width every 2 seconds
    setInterval(() => {
      let newWidth = randomInt(4, 30) * 10;
      foo.style.width = newWidth + 'px';
    }, 2000);
    #foo {
      border: 2px solid #f30;
      width: 100px;
      height: 100px;
      transition: width 1s;
    }
    <div id="foo">foo</div>

    0 讨论(0)
提交回复
热议问题