วิธีการตรวจสอบขนาดของ DIV มีการเปลี่ยนแปลงอย่างไร


352

ฉันได้ html ตัวอย่างต่อไปนี้มี DIV ซึ่งมีความกว้าง 100% มันมีองค์ประกอบบางอย่าง ในขณะที่ทำการปรับขนาดหน้าต่างองค์ประกอบภายในอาจถูกจัดตำแหน่งใหม่และขนาดของ div อาจเปลี่ยนแปลง ฉันถามว่าเป็นไปได้หรือไม่ที่จะเชื่อมโยงกิจกรรมการเปลี่ยนแปลงขนาดของ div และจะทำอย่างไร ขณะนี้ฉันผูกฟังก์ชันการเรียกกลับไปยังเหตุการณ์การปรับขนาด jQuery บน DIV เป้าหมายอย่างไรก็ตามไม่มีการบันทึกคอนโซลที่แสดงผลดูด้านล่าง:

ก่อนปรับขนาด ป้อนคำอธิบายรูปภาพที่นี่

<html>
<head>
    <script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
    <script type="text/javascript" language="javascript">
            $('#test_div').bind('resize', function(){
                console.log('resized');
            });
    </script>
</head>
<body>
    <div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
        <input type="button" value="button 1" />
        <input type="button" value="button 2" />
        <input type="button" value="button 3" />
    </div>
</body>
</html>

7
สิ่งนี้จะไม่ทำงานเนื่องจากคุณผูกกิจกรรมการปรับขนาดกับองค์ประกอบ div ที่ระบุ แต่การปรับขนาดเหตุการณ์จะทริกเกอร์สำหรับหน้าต่างไม่ใช่องค์ประกอบของคุณ
Fatih Acet

คุณสามารถใช้setIntervalที่นี่เป็นวิธีแก้ปัญหาที่เป็นไปได้ คุณสามารถผูกclearIntervalปุ่มคลิกเพื่อหยุดลูปเมื่องานของคุณเสร็จแล้ว
Peter Darmis

1
ตั้งแต่ปี 2563 ResizeObserver สามารถใช้งานได้กับเบราว์เซอร์หลัก (Chrome, Safari, Firefox, Edge) ยกเว้น IE caniuse.com/#feat=resizeobserver
Dan

คำตอบ:


265

มีวิธีที่มีประสิทธิภาพมากในการพิจารณาว่ามีการเปลี่ยนแปลงขนาดขององค์ประกอบหรือไม่

http://marcj.github.io/css-element-queries/

ไลบรารีนี้มีคลาสResizeSensorที่สามารถใช้สำหรับการตรวจหาการปรับขนาด
มันใช้วิธีการตามเหตุการณ์ดังนั้นมันจึงรวดเร็วและไม่เสียเวลาของ CPU

ตัวอย่าง:

new ResizeSensor(jQuery('#divId'), function(){ 
    console.log('content dimension changed');
});

โปรดอย่าใช้ปลั๊กอิน jQuery onresizeเนื่องจากใช้setTimeout()ร่วมกับการอ่าน DOM clientHeight/ clientWidthคุณสมบัติในลูปเพื่อตรวจสอบการเปลี่ยนแปลง
นี้เป็นที่น่าทึ่งช้าและไม่ถูกต้องเพราะมันทำให้เกิดหวดรูปแบบ

การเปิดเผย: ฉันเกี่ยวข้องโดยตรงกับห้องสมุดนี้


8
@jake, IE11 รองรับการใช้งานแล้ว
Marc J. Schmidt

15
@Aletheios คุณควรมองให้ดี requestAnimationFrame ไม่ได้มีไว้สำหรับการตรวจจับมิติที่ช้า แต่ตรงกันข้าม: มันลดจำนวนเหตุการณ์ที่เกิดขึ้นทั้งหมดที่เกิดจากเซ็นเซอร์ปรับขนาดตามเหตุการณ์จริงเพื่อลดเวลาของซีพียู ดูเอกสารที่อัปเดตได้ที่github.com/marcj/css-element-queries/blob/master/src/ …
Marc J. Schmidt

6
@Aletheios ฉันคิดว่าคุณพลาดประเด็น: setTimeout ไม่เพียง แต่ไม่ถูกต้อง แต่ช้าเหมือนนรก RequestAnimationFrame ที่ตรวจสอบบูลีนอย่างง่ายคือคำสั่งที่มีขนาดเร็วกว่า setTimeout ที่ตรวจสอบตลอดเวลากับคุณสมบัติ DOM ข้าง setTimeout นั้นก็เรียกว่าทุก ๆ สองสามมิลลิวินาที
Marc J. Schmidt

9
@Orwellophile เห็นได้ชัดว่าคุณไม่เข้าใจอะไรเลย หยุดคำตอบ downvoting ที่คุณไม่ทราบวิธีการทำงานภายใน อีกครั้ง: css-element-query: ใช้เหตุการณ์การปรับขนาดที่เกิดขึ้นจริงทุกครั้งที่มีการเปลี่ยนแปลงมิติ เนื่องจากคุณได้รับเหตุการณ์มากเกินไป (เช่น drag'n'drop) จึงเพิ่มการตรวจสอบ requestAnimationFrame สำหรับตัวแปรบูลีนแบบง่ายเพื่อปรับกิจกรรมที่ทริกเกอร์ให้ลดลงเหลือ 1 / เฟรม ปลั๊กอิน jquery: ใช้ setTimeout ในการตรวจสอบอุปกรณ์ประกอบฉากของ DOM ตลอดเวลา (clientHeight ฯลฯ ) ซึ่งการตรวจสอบแต่ละครั้งนั้นช้ามาก แต่ต้องมีการตรวจสอบบ่อยครั้งเพื่อให้มีฟังก์ชั่นเดียวกัน
Marc J. Schmidt

9
@Aletheios, @Orwellophile และทุกคนที่อาจจะได้รับโดยพวกเขาเข้าใจผิด: requestAnimationFrameVS setTimeoutเป็นที่ไม่เกี่ยวข้องห้องสมุดนี้ไม่ห่วง requestAnimationFrameจะใช้เพียงเพื่อ debounce / ความถี่ของการเรียกเค้นเรียกกลับของคุณก็ไม่ได้สำรวจความคิดเห็น MutationObserver ในทางทฤษฎีสามารถนำไปใช้กับเอฟเฟกต์ที่คล้ายกันได้ แต่ไม่สามารถใช้กับเบราว์เซอร์รุ่นเก่าได้ นี่คือฉลาดอย่างยอดเยี่ยม
ฮันโซล -Oh

251

มาตรฐานใหม่สำหรับสิ่งนี้คือ apize Observer api ซึ่งมีให้ใน Chrome 64

function outputsize() {
 width.value = textbox.offsetWidth
 height.value = textbox.offsetHeight
}
outputsize()

new ResizeObserver(outputsize).observe(textbox)
Width: <output id="width">0</output><br>
Height: <output id="height">0</output><br>
<textarea id="textbox">Resize me</textarea><br>

ปรับขนาดผู้สังเกตการณ์

ข้อมูลจำเพาะ: https://wicg.github.io/ResizeObserver

Polyfills: https://github.com/WICG/ResizeObserver/issues/3

ปัญหาของ Firefox: https://bugzil.la/1272409

ปัญหา Safari: http://wkb.ug/157743

การสนับสนุนปัจจุบัน: http://caniuse.com/#feat=resizeobserver


3
ยังไม่เป็นประโยชน์สำหรับไซต์การผลิตเนื่องจากมีเพียง Chrome ที่รองรับในขณะนี้ แต่ทางออกที่ดีที่สุดที่นี่แน่นอน! btw ต่อไปนี้เป็นภาพรวมโดยย่อของสถานะการใช้งาน: chromestatus.com/feature/5705346022637568
ฟิลิปส์

8
@ ฟิลิปมีโพลีฟิล
Daniel Herr

2
ดูเหมือนว่ามันยังคงเป็นคุณลักษณะทดลองในเบราว์เซอร์ทั้งหมดcaniuse.com/#feat=resizeobserver
Francesc Rosas

5
แม้กระทั่ง 2 ปีหลังจากคำตอบนี้การสนับสนุนเบราว์เซอร์ก็ยังคงเยือกเย็น: caniuse.com/#search=resizeobserver
Scrimothy

2
ใช้งานได้อย่างมีเสน่ห์ใน Chrome และ FF ล่าสุด
Klemen Tušar

32

คุณต้องผูกresizeเหตุการณ์บนwindowวัตถุไม่ใช่ในองค์ประกอบ html ทั่วไป

จากนั้นคุณสามารถใช้สิ่งนี้:

$(window).resize(function() {
    ...
});

และภายในฟังก์ชั่นการโทรกลับคุณสามารถตรวจสอบความกว้างใหม่ของการdivโทรของคุณ

$('.a-selector').width();

ดังนั้นคำตอบสำหรับคำถามของคุณคือไม่คุณไม่สามารถผูกresizeเหตุการณ์ให้กับ div


124
คำตอบนี้ไม่ดีพอ การเปลี่ยนแปลงขนาดอาจเกิดขึ้นโดยไม่มีการปรับขนาดหน้าต่างใด ๆ เลย
vsync

9
ตัวอย่างเช่นเมื่อคุณมีองค์ประกอบแยกหรือเพียงผนวกข้อความหรือเนื้อหาอื่น ๆ ในองค์ประกอบ
GünterZöchbauer

@anu ไม่เป็นความจริงคุณสามารถมีตัวอย่างเช่นการแก้ไข DOM ผ่าน javascript ทำให้ CSS ใช้กับโครงสร้างใหม่ทำให้มีขนาดต่างกันของทุกคอนเทนเนอร์
Antoniossss

29

ในระยะยาวคุณจะสามารถที่จะใช้ResizeObserver

new ResizeObserver(callback).observe(element);

น่าเสียดายที่ปัจจุบันยังไม่รองรับเบราว์เซอร์จำนวนมาก

ในเวลาเฉลี่ยคุณสามารถใช้ฟังก์ชั่นดังนี้ เนื่องจากการเปลี่ยนแปลงขนาดองค์ประกอบส่วนใหญ่จะมาจากการปรับขนาดหน้าต่างหรือการเปลี่ยนแปลงบางอย่างใน DOM คุณสามารถฟังการปรับขนาดหน้าต่างด้วยเหตุการณ์การปรับขนาดของหน้าต่างและคุณสามารถฟังการเปลี่ยนแปลง DOM โดยใช้MutationObserver MutationObserver

นี่คือตัวอย่างของฟังก์ชั่นที่จะโทรกลับหาคุณเมื่อขนาดขององค์ประกอบที่มีให้มีการเปลี่ยนแปลงเนื่องจากเหตุการณ์อย่างใดอย่างหนึ่งดังต่อไปนี้:

var onResize = function(element, callback) {
  if (!onResize.watchedElementData) {
    // First time we are called, create a list of watched elements
    // and hook up the event listeners.
    onResize.watchedElementData = [];

    var checkForChanges = function() {
      onResize.watchedElementData.forEach(function(data) {
        if (data.element.offsetWidth !== data.offsetWidth ||
            data.element.offsetHeight !== data.offsetHeight) {
          data.offsetWidth = data.element.offsetWidth;
          data.offsetHeight = data.element.offsetHeight;
          data.callback();
        }
      });
    };

    // Listen to the window's size changes
    window.addEventListener('resize', checkForChanges);

    // Listen to changes on the elements in the page that affect layout 
    var observer = new MutationObserver(checkForChanges);
    observer.observe(document.body, { 
      attributes: true,
      childList: true,
      characterData: true,
      subtree: true 
    });
  }

  // Save the element we are watching
  onResize.watchedElementData.push({
    element: element,
    offsetWidth: element.offsetWidth,
    offsetHeight: element.offsetHeight,
    callback: callback
  });
};

1
น่าเสียดายที่ดูเหมือนว่า MutationObserver ไม่สามารถตรวจพบการเปลี่ยนแปลงใน Shadow DOM
Ajedi32

@nkron น่าเสียดายถ้าคุณใช้การปรับขนาด CSS3 การปรับขนาดอาจเกิดขึ้นได้เมื่อผู้ใช้ปรับขนาดด้วยตนเอง ไม่สามารถจับกิจกรรมนี้ได้
Pacerier

@ Ajedi32 ใช่ แต่คุณสามารถใช้ MutationObserver ภายใน ShadowDOM สิ่งที่ฉันหมายถึงคือแทนที่จะดูbodyในตัวอย่างนี้คุณสามารถดูองค์ประกอบได้โดยตรง ที่จริงแล้วมันมีประสิทธิภาพและประสิทธิภาพมากกว่าการเฝ้าดูทั้งร่างกาย
trusktr

@ Ajedi32 เอาล่ะปัญหาเดียวก็คือถ้าปิด Shadow DOM tree แล้วคุณจะไม่สามารถเข้าถึง internals ได้ แต่ฉันไม่คิดว่ามันเป็นสิ่งที่คุณต้องทำและถ้าคุณต้องสังเกต ต้นไม้ปิดแบบนั้นอาจมีปัญหาในการออกแบบ เป็นการดีที่คุณควรจะสังเกตองค์ประกอบของตัวเองที่คุณสามารถเข้าถึงได้ องค์ประกอบ Shadow-DOM ที่ต้องการให้คุณสังเกตว่าการปรับขนาดภายในอาจไม่ได้รับการออกแบบอย่างเหมาะสม คุณมีตัวอย่างเฉพาะหรือไม่ ถ้าเป็นเช่นนั้นฉันอาจช่วยแนะนำวิธีแก้ปัญหาได้ (เพราะฉันก็สนใจเหมือนกัน แต่ยังไม่มีตัวอย่าง)
trusktr

@trusktr ฉันไม่มี MCVE ในขณะนี้ แต่โดยทั่วไปองค์ประกอบ Shadow DOM ใด ๆ ที่สามารถเปลี่ยนขนาดได้เนื่องจากการป้อนข้อมูลของผู้ใช้บางรายจะเพียงพอที่จะทำให้เกิดปัญหานี้ ตัวอย่างกล่องที่ขยายออกมาพร้อมข้อมูลเพิ่มเติมบางส่วนเมื่อคลิกตัวอย่างเช่น โปรดทราบว่าฉันกำลังดูหน้าเว็บไม่ใช่องค์ประกอบแต่ละอันเพราะฉันต้องการเลื่อนลงโดยอัตโนมัติเมื่อขนาดของหน้าเพิ่มขึ้นโดยไม่คำนึงถึงเหตุผล องค์ประกอบเงา DOM ขยายเป็นเพียงหนึ่งในหลายเหตุผลที่เป็นไปได้ว่าทำไมหน้าอาจจะนานขึ้น
Ajedi32

24

ResizeSensor.jsเป็นส่วนหนึ่งของห้องสมุดขนาดใหญ่ แต่ผมลดฟังก์ชันการทำงานในการนี้ :

function ResizeSensor(element, callback)
{
    let zIndex = parseInt(getComputedStyle(element));
    if(isNaN(zIndex)) { zIndex = 0; };
    zIndex--;

    let expand = document.createElement('div');
    expand.style.position = "absolute";
    expand.style.left = "0px";
    expand.style.top = "0px";
    expand.style.right = "0px";
    expand.style.bottom = "0px";
    expand.style.overflow = "hidden";
    expand.style.zIndex = zIndex;
    expand.style.visibility = "hidden";

    let expandChild = document.createElement('div');
    expandChild.style.position = "absolute";
    expandChild.style.left = "0px";
    expandChild.style.top = "0px";
    expandChild.style.width = "10000000px";
    expandChild.style.height = "10000000px";
    expand.appendChild(expandChild);

    let shrink = document.createElement('div');
    shrink.style.position = "absolute";
    shrink.style.left = "0px";
    shrink.style.top = "0px";
    shrink.style.right = "0px";
    shrink.style.bottom = "0px";
    shrink.style.overflow = "hidden";
    shrink.style.zIndex = zIndex;
    shrink.style.visibility = "hidden";

    let shrinkChild = document.createElement('div');
    shrinkChild.style.position = "absolute";
    shrinkChild.style.left = "0px";
    shrinkChild.style.top = "0px";
    shrinkChild.style.width = "200%";
    shrinkChild.style.height = "200%";
    shrink.appendChild(shrinkChild);

    element.appendChild(expand);
    element.appendChild(shrink);

    function setScroll()
    {
        expand.scrollLeft = 10000000;
        expand.scrollTop = 10000000;

        shrink.scrollLeft = 10000000;
        shrink.scrollTop = 10000000;
    };
    setScroll();

    let size = element.getBoundingClientRect();

    let currentWidth = size.width;
    let currentHeight = size.height;

    let onScroll = function()
    {
        let size = element.getBoundingClientRect();

        let newWidth = size.width;
        let newHeight = size.height;

        if(newWidth != currentWidth || newHeight != currentHeight)
        {
            currentWidth = newWidth;
            currentHeight = newHeight;

            callback();
        }

        setScroll();
    };

    expand.addEventListener('scroll', onScroll);
    shrink.addEventListener('scroll', onScroll);
};

วิธีใช้งาน:

let container = document.querySelector(".container");
new ResizeSensor(container, function()
{
    console.log("dimension changed:", container.clientWidth, container.clientHeight);
});

นี่คือสิ่งที่แผนภูมิ js ทำ
Antoniossss

ขอบคุณที่อัดมัน ฉันจะลองทำ :)
Tony K.

มีบางอย่างขาดหายไปในนิพจน์นี้parseInt( getComputedStyle(element) )
GetFree

2
ฉันสับสนว่า "let zIndex = parseInt (getComputedStyle (องค์ประกอบ))"; ถูกต้อง? ฉันคิดว่าคุณหมายถึง: "ให้ zIndex = parseInt (getComputedStyle (องค์ประกอบ) .zIndex);
Ryan Badour

1
วิธีแก้ไขปัญหา / รหัสด้านบนตรวจไม่พบเหตุการณ์การปรับขนาดทั้งหมด (เช่นหากมีการปรับขนาดคอนเทนเนอร์เป็นแบบคงที่ด้วยจะไม่ตรวจหาการปรับขนาดสำหรับเหตุการณ์ลูกดูjsfiddle.net/8md2rfsy/1 ) คำตอบที่ได้รับการยอมรับทำงาน (uncomment บรรทัดที่เกี่ยวข้อง)
newBee

21

ฉันไม่แนะนำให้setTimeout()แฮ็คเพราะจะทำให้ประสิทธิภาพช้าลง! แต่คุณสามารถใช้ ผู้สังเกตการณ์การกลายพันธุ์ DOMเพื่อรับฟังการเปลี่ยนแปลงขนาด Div

JS:

var observer = new MutationObserver(function(mutations) {
    console.log('size changed!');
  });
  var target = document.querySelector('.mydiv');
  observer.observe(target, {
    attributes: true
  });

HTML:

<div class='mydiv'>
</div>

นี่คือซอ
พยายามเปลี่ยนขนาด div


คุณสามารถสรุปวิธีการในdebounceการปรับปรุงประสิทธิภาพ debounceจะเรียกวิธีการของคุณทุก ๆ x มิลลิวินาทีแทนการกระตุ้นทุกมิลลิวินาทีที่ DIV กำลังถูกปรับขนาด


9
ปัญหาเดียวของอันนี้ก็คือมันไม่ได้รายงานการเปลี่ยนแปลงเว้นแต่ว่าการกลายพันธุ์จะเกิดขึ้นกับองค์ประกอบ หากองค์ประกอบมีการปรับขนาดเนื่องจากมีการเพิ่มองค์ประกอบอื่น ๆ สิ่งนี้จะไม่ทำงาน
Tony K.

ฉันเห็นด้วยกับ @TonyK. นี่เป็นปัญหาเดียวของฉันกับ MutationObserver และตอนนี้ฉันกำลังมองหาห้องสมุดปรับขนาดองค์ประกอบ
Murhaf Sousli

@JerryGoyal มันไม่ทำงานเมื่อ div มีแท็ก <img> ในอินสแตนซ์แรกรูปภาพจะไม่ถูกโหลดและขนาด div ถูกตั้งค่าเป็น 0 และหลังจากโหลดขนาด div จะถูกเปลี่ยน แต่ผู้สังเกตการณ์ไม่ถูกทริกเกอร์
Santhosh

15

ทางออกที่ดีที่สุดคือการใช้องค์ประกอบการค้นหาที่เรียกว่าธาตุแบบสอบถามอย่างไรก็ตามมันไม่ได้เป็นแบบมาตรฐานไม่มีข้อกำหนดอยู่ - และตัวเลือกเดียวคือใช้หนึ่งใน polyfills / ไลบรารีที่มีอยู่หากคุณต้องการใช้วิธีนี้

แนวคิดเบื้องหลังการสืบค้นองค์ประกอบคือการอนุญาตให้คอนเทนเนอร์บางอย่างในหน้าตอบสนองต่อพื้นที่ที่มีให้ การทำเช่นนี้จะช่วยให้สามารถเขียนส่วนประกอบหนึ่งครั้งแล้วปล่อยไปที่ใดก็ได้บนหน้าในขณะที่มันจะปรับเนื้อหาให้มีขนาดปัจจุบัน ไม่ว่าขนาดหน้าต่างจะเป็นเท่าไหร่ นี่คือความแตกต่างแรกที่เราเห็นระหว่างเคียวรีองค์ประกอบและเคียวรีสื่อบันทึก ทุกคนหวังว่าในบางจุดข้อมูลจำเพาะจะถูกสร้างขึ้นที่จะสร้างมาตรฐานข้อความค้นหาองค์ประกอบ (หรือบางสิ่งที่บรรลุเป้าหมายเดียวกัน) และทำให้เป็นภาษาดั้งเดิมสะอาดเรียบง่ายและแข็งแกร่ง คนส่วนใหญ่ยอมรับว่าข้อความค้นหาสื่อค่อนข้าง จำกัด และไม่ช่วยในการออกแบบแบบแยกส่วนและตอบสนองที่แท้จริง

มีโพลีฟิล / ไลบรารี่สองสามตัวที่แก้ปัญหาด้วยวิธีที่ต่างกัน (อาจเรียกว่าการแก้ปัญหาแทนที่จะเป็นวิธีแก้ปัญหา):

ฉันได้เห็นวิธีแก้ไขปัญหาอื่น ๆ สำหรับปัญหาที่คล้ายกันที่เสนอ พวกเขามักจะใช้ตัวจับเวลาหรือขนาด Window / viewport ภายใต้ประทุนซึ่งไม่ใช่วิธีการแก้ปัญหาจริง นอกจากนี้ฉันคิดว่าสิ่งนี้ควรแก้ไขใน CSS เป็นหลักและไม่ใช่ใน javascript หรือ html


+1 สำหรับข้อความค้นหาองค์ประกอบ แต่ฉันไม่หวังว่าจะเห็นพวกเขาทุกเวลาเร็ว ๆ นี้ ในตอนนี้ยังไม่มีร่างสเปค AFAIK ... อาจเป็นหนึ่งในพวกเราที่สนใจควรรวมเข้าด้วยกันและส่งหรือไม่
Rob Evans

1
นั่นเป็นความคิดที่ดีแน่นอน ใช้เวลานานกว่าจะถึงรุ่นสุดท้ายต้องให้ความสนใจอย่างมาก การออกแบบสิ่งนี้ในทางที่ดีดูเหมือนจะไม่สำคัญกับฉัน เข้ากันได้ข้ามเบราว์เซอร์อ้างอิงวงกลมแก้จุดบกพร่องการอ่านและการบำรุงรักษา ฯลฯ ดังนั้นขอเริ่มต้นเร็วที่สุดเท่าที่เป็นไปได้ :)
สแตน

@ สแตนฉันคิดว่าคำตอบนี้จะดีขึ้นโดยการเพิ่มรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่องค์ประกอบแบบสอบถามคือทั้งหมดที่เกี่ยวกับ
Pacerier

15

ฉันพบว่าห้องสมุดนี้จะทำงานเมื่อทางออกของ MarcJ ไม่ได้:

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

มันมีน้ำหนักเบามากและตรวจจับได้อย่างเป็นธรรมชาติแม้ปรับขนาดด้วย CSS หรือเพียงแค่โหลด / แสดงผล HTML

ตัวอย่างโค้ด (นำมาจากลิงก์):

<script type="text/javascript" src="detect-element-resize.js"></script>
<script type="text/javascript">
  var resizeElement = document.getElementById('resizeElement'),
      resizeCallback = function() {
          /* do something */
      };
  addResizeListener(resizeElement, resizeCallback);
  removeResizeListener(resizeElement, resizeCallback);
</script>

นี่ไง. 147 บรรทัดใช้เหตุการณ์การเลื่อน อ่านรหัสนี้หากคุณต้องการคำตอบที่สมบูรณ์และเป็นจริงเกี่ยวกับวิธีการตรวจจับการเปลี่ยนแปลงขนาด div คำแนะนำ: ไม่ใช่ "เพียงใช้ไลบรารีนี้"
Seph Reed

1
ผู้ใช้ควรดูที่ปัญหานี้ก่อนลองใช้ห้องสมุดนี้
หลุยส์

13

ดูที่http://benalman.com/code/projects/jquery-resize/examples/resize/นี้

มันมีตัวอย่างมากมาย ลองปรับขนาดหน้าต่างของคุณและดูว่าองค์ประกอบต่างๆในองค์ประกอบคอนเทนเนอร์ได้รับการปรับแต่งอย่างไร

ตัวอย่างกับซอ js เพื่ออธิบายวิธีการทำงาน
ดูซอนี้http://jsfiddle.net/sgsqJ/4/

ในเหตุการณ์ที่ปรับขนาด () ถูกผูกไว้กับองค์ประกอบที่มีระดับ "ทดสอบ" และวัตถุหน้าต่างและในการปรับขนาดโทรกลับของวัตถุหน้าต่าง $ ('. ทดสอบ') ปรับขนาด () เรียกว่า

เช่น

$('#test_div').bind('resize', function(){
            console.log('resized');
});

$(window).resize(function(){
   $('#test_div').resize();
});

น่าสนใจ jsfiddle นั้นขัดข้องกับโครมอย่างสม่ำเสมอด้วยตัวตรวจสอบที่เปิดอยู่และฉันคลิกที่ลิงค์ "เพิ่มข้อความเพิ่มเติม" Firefox พ่นข้อผิดพลาด "การเรียกซ้ำมากเกินไป"
EricP

3
โปรดอย่าใช้ปลั๊กอินปรับขนาดของ jQuery มันช้ามากและไม่ถูกต้องเช่นกัน ดูคำตอบของฉันเพื่อรับทางออกที่ดีกว่า
Marc J. Schmidt

24
สิ่งนี้ไม่ได้ตรวจพบการเปลี่ยนแปลงขนาดโดยตรง มันเป็นเพียงผลพลอยได้จากผู้ปรับขนาดเหตุการณ์ การเปลี่ยนแปลงมิติสามารถเกิดขึ้นได้หลายวิธี
vsync

4
เกิดอะไรขึ้นถ้าขนาดของ div มาจากการเปลี่ยนแปลงในรูปแบบหรือ dom และไม่ใช่โดยการปรับขนาดหน้าต่าง
ความกลัว

9

คุณสามารถใช้iframeหรือobjectใช้contentWindowหรือcontentDocumentปรับขนาด โดยไม่ต้องsetIntervalหรือsetTimeout

ขั้นตอน:

  1. ตั้งตำแหน่งองค์ประกอบของคุณเป็น relative
  2. เพิ่มภายใน IFRAME ที่ซ่อนอยู่อย่างสมบูรณ์แบบโปร่งใส
  3. ฟังIFRAME.contentWindow- onresizeกิจกรรม

ตัวอย่างของ HTML:

<div style="height:50px;background-color:red;position:relative;border:1px solid red">
<iframe style=width:100%;height:100%;position:absolute;border:none;background-color:transparent allowtransparency=true>
</iframe>
This is my div
</div>

Javascript:

$('div').width(100).height(100);
$('div').animate({width:200},2000);

$('object').attr({
    type : 'text/html'
})
$('object').on('resize,onresize,load,onload',function(){
    console.log('ooooooooonload')
})

$($('iframe')[0].contentWindow).on('resize',function(){
    console.log('div changed')
})

ตัวอย่างการวิ่ง

JsFiddle: https://jsfiddle.net/qq8p470d/


ดูเพิ่มเติม:


1
หมายเหตุสำหรับผู้ที่ไม่ได้ใช้ jQuery IFRAME.contentWindowจะไม่สามารถใช้งานได้จนกว่าonloadเหตุการณ์จะเกิดขึ้นบน iframe นอกจากนี้คุณอาจต้องการเพิ่มสไตล์visibility:hidden;เนื่องจาก iframe สามารถบล็อกอินพุตของเมาส์ไปยังองค์ประกอบที่อยู่ด้านหลัง (ดูเหมือนจะเป็น "floating" ใน IE อย่างน้อย)
James Wilkins

3
แม้ว่าจะใช้งานได้ แต่เป็นโซลูชันที่มีน้ำหนักมากพร้อมค่าใช้จ่ายในการสร้างบริบทการสืบค้นใหม่ทั้งหมดเพียงเพื่อสังเกตการเปลี่ยนแปลงขนาด นอกจากนี้ในบางกรณีมันไม่เหมาะหรือเป็นไปได้ที่จะเปลี่ยนdisplayคุณสมบัติขององค์ประกอบ
trusktr

ตกลงนี้เป็นวิธีการแก้ปัญหาที่น่ากลัวตามที่ระบุไว้ข้างต้น
29er

เขียนวิธีแก้ปัญหาที่น่ากลัวมากได้อย่างไร
Aminadav Glickshtein

วิธีนี้ใช้ได้ดีกับเครื่องเล่นวิดีโอและเครื่องเล่นเสียงที่ต้องการปรับขนาดเนื้อหาแบบไดนามิก ฉันใช้วิธีการนี้เพื่อปรับขนาดเอาต์พุตคลื่นวิทยุ
David Clews

8

เฉพาะวัตถุหน้าต่างสร้างเหตุการณ์ "ปรับขนาด" วิธีเดียวที่ฉันรู้ในการทำสิ่งที่คุณต้องการคือการเรียกใช้ตัวจับเวลาช่วงเวลาที่ตรวจสอบขนาดเป็นระยะ


7

var div = document.getElementById('div');
div.addEventListener('resize', (event) => console.log(event.detail));

function checkResize (mutations) {
    var el = mutations[0].target;
    var w = el.clientWidth;
    var h = el.clientHeight;
    
    var isChange = mutations
      .map((m) => m.oldValue + '')
      .some((prev) => prev.indexOf('width: ' + w + 'px') == -1 || prev.indexOf('height: ' + h + 'px') == -1);

    if (!isChange)
      return;

    var event = new CustomEvent('resize', {detail: {width: w, height: h}});
    el.dispatchEvent(event);
}

var observer = new MutationObserver(checkResize); 
observer.observe(div, {attributes: true, attributeOldValue: true, attributeFilter: ['style']});
#div {width: 100px; border: 1px solid #bbb; resize: both; overflow: hidden;}
<div id = "div">DIV</div>


7

น่าประหลาดใจที่ปัญหานี้ยังคงเป็นปัญหาในเบราว์เซอร์ส่วนใหญ่

ขณะที่คนอื่น ๆ ได้กล่าวว่า Chrome 64+ ตอนนี้มาพร้อมกับการปรับขนาดสังเกตโดยกำเนิด แต่สเปคยังคงถูกปรับปรับและ Chrome คือตอนนี้ในปัจจุบัน ( ณ วันที่ 2019/01/29) ที่อยู่เบื้องหลังรุ่นล่าสุดของสเปค

ฉันเคยเห็นโพลีฟิลที่ดี ResizeObserver สองสามตัวในป่า แต่บางคนไม่ปฏิบัติตามข้อกำหนดที่ใกล้ชิดและคนอื่น ๆ มีปัญหาในการคำนวณ

ฉันต้องการพฤติกรรมนี้อย่างสิ้นหวังเพื่อสร้างองค์ประกอบของเว็บที่ตอบสนองได้ดีซึ่งสามารถนำไปใช้กับแอปพลิเคชันใด ๆ ได้ เพื่อให้มันทำงานได้อย่างดีพวกเขาจำเป็นต้องรู้ขนาดของมันตลอดเวลาดังนั้น ResizeObservers จึงฟังดูดีและฉันตัดสินใจที่จะสร้างโพลีฟิลที่เป็นไปตามสเป็คที่ใกล้เคียงที่สุด

Repo: https://github.com/juggle/resize-observer

การสาธิต: https://codesandbox.io/s/myqzvpmmy9


นี่คือคำตอบที่รุมเร้าสำหรับทุกคนที่เกี่ยวข้องกับความเข้ากันได้ของเบราว์เซอร์ IE11 +
ekfuhrmann

3

การใช้ Clay.js ( https://github.com/zzarcon/clay ) มันค่อนข้างง่ายในการตรวจจับการเปลี่ยนแปลงขนาดองค์ประกอบ:

var el = new Clay('.element');

el.on('resize', function(size) {
    console.log(size.height, size.width);
});

7
โปรดให้ข้อมูลที่เหมาะสมเนื่องจากเป็นห้องสมุดของคุณ
jhpratt GOFUNDME RELICENSING

สิ่งนี้ใช้ได้กับฉันโดยที่ ResizeSensor ไม่ได้ทำให้สไตล์โมดอลของฉันแตกสลาย ขอบคุณ Zzarcon :)
Máxima Alekz

3

โพสต์บล็อกนี้ช่วยให้ฉันตรวจจับการเปลี่ยนแปลงขนาดขององค์ประกอบ DOM ได้อย่างมีประสิทธิภาพ

http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/

วิธีใช้รหัสนี้ ...

AppConfig.addResizeListener(document.getElementById('id'), function () {
  //Your code to execute on resize.
});

รหัสแพคเกจที่ใช้โดยตัวอย่าง ...

var AppConfig = AppConfig || {};
AppConfig.ResizeListener = (function () {
    var attachEvent = document.attachEvent;
    var isIE = navigator.userAgent.match(/Trident/);
    var requestFrame = (function () {
        var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
            function (fn) { return window.setTimeout(fn, 20); };
        return function (fn) { return raf(fn); };
    })();

    var cancelFrame = (function () {
        var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
               window.clearTimeout;
        return function (id) { return cancel(id); };
    })();

    function resizeListener(e) {
        var win = e.target || e.srcElement;
        if (win.__resizeRAF__) cancelFrame(win.__resizeRAF__);
        win.__resizeRAF__ = requestFrame(function () {
            var trigger = win.__resizeTrigger__;
            trigger.__resizeListeners__.forEach(function (fn) {
                fn.call(trigger, e);
            });
        });
    }

    function objectLoad(e) {
        this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
        this.contentDocument.defaultView.addEventListener('resize', resizeListener);
    }

    AppConfig.addResizeListener = function (element, fn) {
        if (!element.__resizeListeners__) {
            element.__resizeListeners__ = [];
            if (attachEvent) {
                element.__resizeTrigger__ = element;
                element.attachEvent('onresize', resizeListener);
            } else {
                if (getComputedStyle(element).position === 'static') element.style.position = 'relative';
                var obj = element.__resizeTrigger__ = document.createElement('object');
                obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
                obj.__resizeElement__ = element;
                obj.onload = objectLoad;
                obj.type = 'text/html';
                if (isIE) element.appendChild(obj);
                obj.data = 'about:blank';
                if (!isIE) element.appendChild(obj);
            }
        }
        element.__resizeListeners__.push(fn);
    };

    AppConfig.removeResizeListener = function (element, fn) {
        element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
        if (!element.__resizeListeners__.length) {
            if (attachEvent) element.detachEvent('onresize', resizeListener);
            else {
                element.__resizeTrigger__.contentDocument.defaultView.removeEventListener('resize', resizeListener);
                element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
            }
        }
    }
})();

หมายเหตุ: AppConfig เป็น namespace / object ที่ฉันใช้สำหรับจัดระเบียบฟังก์ชั่นที่ใช้ซ้ำได้ ค้นหาและแทนที่ชื่อด้วยทุกสิ่งที่คุณต้องการ


3

ปลั๊กอิน jQuery ของฉันเปิดใช้งานเหตุการณ์ "ปรับขนาด" ในองค์ประกอบทั้งหมดไม่ใช่เฉพาะ windowเหตุการณ์เมื่อองค์ประกอบทั้งหมดไม่ได้เป็นเพียง

https://github.com/dustinpoissant/ResizeTriggering

$("#myElement") .resizeTriggering().on("resize", function(e){
  // Code to handle resize
}); 

1
ลิงก์ของคุณชี้ไปยังตำแหน่งที่ไม่มีอยู่อีกต่อไป ฉันค้นหาชื่อปลั๊กอินแล้วพบหน้าเว็บที่ตรงกับคำอธิบายของคุณ เนื่องจากคุณดูเหมือนจะเป็นผู้เขียนปลั๊กอินฉันจึงได้แก้ไขภาษาของคำตอบของคุณเพื่อให้ชัดเจนว่านี่คืองานของคุณ กฎของเว็บไซต์นี้เป็นเช่นนั้นเมื่อคุณเขียนคำตอบแนะนำให้ใช้สิ่งที่คุณพัฒนาขึ้นคุณต้องทำให้ความสัมพันธ์ชัดเจน
หลุยส์

นี่ไม่ใช่วิธีแก้ปัญหาที่ยอดเยี่ยมเพราะคุณเรียกใช้ฟังก์ชั่นบางอย่างใน setTimer ซ้ำแล้วซ้ำอีกซึ่งหมายความว่าเบราว์เซอร์จะเผา CPU อย่างต่อเนื่องแม้ว่าจะไม่มีอะไรเกิดขึ้น เจ้าของแล็ปท็อปและโทรศัพท์มือถือจะได้รับประโยชน์จากโซลูชันที่ใช้กิจกรรมเบราว์เซอร์เมื่อมีการดำเนินการบางอย่างเท่านั้นเช่นการใช้งานกิจกรรม onScroll
Roman Zenka

2

คุณสามารถลองรหัสในตัวอย่างต่อไปนี้ซึ่งจะครอบคลุมความต้องการของคุณโดยใช้จาวาสคริปต์ธรรมดา ( เรียกใช้ข้อมูลโค้ดและคลิกลิงก์เต็มหน้าเพื่อกระตุ้นการแจ้งเตือนว่า div ถูกปรับขนาดถ้าคุณต้องการทดสอบ )

จากความจริงที่ว่านี่เป็นsetInterval100 มิลลิวินาทีฉันจะกล้าพูดว่าพีซีของฉันไม่พบ CPU ที่หิวมากเกินไป (0.1% ของ CPU ถูกใช้เป็นยอดรวมสำหรับแท็บที่เปิดอยู่ทั้งหมดใน Chrome ในขณะที่ทำการทดสอบ) แต่อีกครั้งนี่เป็นเพียงหนึ่ง div ถ้าคุณต้องการทำสิ่งนี้สำหรับองค์ประกอบจำนวนมากแล้วใช่มันอาจจะเป็น CPU ที่หิวมาก

คุณสามารถใช้เหตุการณ์คลิกเพื่อหยุดการดมกลิ่น div-resize ได้

var width = 0; 
var interval = setInterval(function(){
if(width <= 0){
width = document.getElementById("test_div").clientWidth;
} 
if(document.getElementById("test_div").clientWidth!==width) {   
  alert('resized div');
  width = document.getElementById("test_div").clientWidth;
}    

}, 100);
<div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
        <input type="button" value="button 1" />
        <input type="button" value="button 2" />
        <input type="button" value="button 3" />
</div>

คุณสามารถตรวจสอบซอได้

UPDATE

var width = 0; 
function myInterval() {
var interval = setInterval(function(){
if(width <= 0){
width = document.getElementById("test_div").clientWidth;
} 
if(document.getElementById("test_div").clientWidth!==width) {   
  alert('resized');
  width = document.getElementById("test_div").clientWidth;
}    

}, 100);
return interval;
}
var interval = myInterval();
document.getElementById("clickMe").addEventListener( "click" , function() {
if(typeof interval!=="undefined") {
clearInterval(interval);
alert("stopped div-resize sniffing");
}
});
document.getElementById("clickMeToo").addEventListener( "click" , function() {
myInterval();
alert("started div-resize sniffing");
});
<div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
        <input type="button" value="button 1" id="clickMe" />
        <input type="button" value="button 2" id="clickMeToo" />
        <input type="button" value="button 3" />
</div>

อัพเดตซอ


2

นี่เป็นคำตอบที่ถูกต้อง แต่เป็นส่วนหนึ่งของรหัสที่แปลว่า IMO สามารถอ่านและเข้าใจได้ง่ายขึ้น การเปลี่ยนแปลงเล็ก ๆ น้อย ๆ อื่น ๆ ได้แก่ การใช้ cloneNode () และไม่ใส่ html ลงในสตริง js สิ่งเล็ก ๆ แต่คุณสามารถคัดลอกและวางตามที่มันเป็นและมันจะทำงาน

วิธีการทำงานคือการทำให้ div ที่มองไม่เห็นสองตัวเติมองค์ประกอบที่คุณกำลังดูอยู่จากนั้นจึงเปิดทริกเกอร์ในแต่ละครั้งและตั้งค่าตำแหน่งการเลื่อนที่จะทำให้เกิดการเปลี่ยนแปลงการเลื่อนหากขนาดมีการเปลี่ยนแปลง

เครดิตที่แท้จริงทั้งหมดไปที่ Marc J แต่หากคุณเพียงแค่มองหารหัสที่เกี่ยวข้องนี่คือ:

    window.El = {}

    El.resizeSensorNode = undefined;
    El.initResizeNode = function() {
        var fillParent = "display: block; position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;";
        var triggerStyle = "position: absolute; left: 0; top: 0; transition: 0s;";

        var resizeSensor = El.resizeSensorNode = document.createElement("resizeSensor");
        resizeSensor.style = fillParent;

        var expandSensor = document.createElement("div");
        expandSensor.style = fillParent;
        resizeSensor.appendChild(expandSensor);

        var trigger = document.createElement("div");
        trigger.style = triggerStyle;
        expandSensor.appendChild(trigger);

        var shrinkSensor = expandSensor.cloneNode(true);
        shrinkSensor.firstChild.style = triggerStyle + " width: 200%; height: 200%";
        resizeSensor.appendChild(shrinkSensor);
    }


    El.onSizeChange = function(domNode, fn) {
        if (!domNode) return;
        if (domNode.resizeListeners) {
            domNode.resizeListeners.push(fn);
            return;
        }

        domNode.resizeListeners = [];
        domNode.resizeListeners.push(fn);

        if(El.resizeSensorNode == undefined)
            El.initResizeNode();

        domNode.resizeSensor = El.resizeSensorNode.cloneNode(true);
        domNode.appendChild(domNode.resizeSensor);

        var expand = domNode.resizeSensor.firstChild;
        var expandTrigger = expand.firstChild;
        var shrink = domNode.resizeSensor.childNodes[1];

        var reset = function() {
            expandTrigger.style.width = '100000px';
            expandTrigger.style.height = '100000px';

            expand.scrollLeft = 100000;
            expand.scrollTop = 100000;

            shrink.scrollLeft = 100000;
            shrink.scrollTop = 100000;
        };

        reset();

        var hasChanged, frameRequest, newWidth, newHeight;
        var lastWidth = domNode.offsetWidth;
        var lastHeight = domNode.offsetHeight;


        var onResized = function() {
            frameRequest = undefined;

            if (!hasChanged) return;

            lastWidth = newWidth;
            lastHeight = newHeight;

            var listeners = domNode.resizeListeners;
            for(var i = 0; listeners && i < listeners.length; i++) 
                listeners[i]();
        };

        var onScroll = function() {
            newWidth = domNode.offsetWidth;
            newHeight = domNode.offsetHeight;
            hasChanged = newWidth != lastWidth || newHeight != lastHeight;

            if (hasChanged && !frameRequest) {
                frameRequest = requestAnimationFrame(onResized);
            }

            reset();
        };


        expand.addEventListener("scroll", onScroll);
        shrink.addEventListener("scroll", onScroll);
    }

1

โซลูชัน Javascript เพียว แต่ใช้ได้เฉพาะเมื่อองค์ประกอบถูกปรับขนาดด้วยปุ่มปรับขนาด css :

  1. ขนาดองค์ประกอบร้านค้าที่มีoffsetWidthและoffsetHeight ;
  2. เพิ่มฟังเหตุการณ์onclickในองค์ประกอบนี้
  3. เมื่อมีการเรียกเปรียบเทียบ curent offsetWidthและoffsetHeightมีค่าเก็บไว้และถ้าแตกต่างกันทำในสิ่งที่คุณต้องการและปรับปรุงค่าเหล่านี้

1

นี่เป็นเวอร์ชันที่ง่ายของการแก้ปัญหาโดย @nkron ใช้กับองค์ประกอบเดียว (แทนที่จะเป็นอาร์เรย์ขององค์ประกอบในคำตอบของ @ nkron ความซับซ้อนที่ฉันไม่ต้องการ)

function onResizeElem(element, callback) {    
  // Save the element we are watching
  onResizeElem.watchedElementData = {
    element: element,
    offsetWidth: element.offsetWidth,
    offsetHeight: element.offsetHeight,
    callback: callback
  };

  onResizeElem.checkForChanges = function() {
    const data = onResizeElem.watchedElementData;
    if (data.element.offsetWidth !== data.offsetWidth || data.element.offsetHeight !== data.offsetHeight) {
      data.offsetWidth = data.element.offsetWidth;
      data.offsetHeight = data.element.offsetHeight;
      data.callback();
    }
  };

  // Listen to the window resize event
  window.addEventListener('resize', onResizeElem.checkForChanges);

  // Listen to the element being checked for width and height changes
  onResizeElem.observer = new MutationObserver(onResizeElem.checkForChanges);
  onResizeElem.observer.observe(document.body, {
    attributes: true,
    childList: true,
    characterData: true,
    subtree: true
  });
}

ผู้ฟังและผู้สังเกตการณ์เหตุการณ์สามารถลบออกได้โดย:

window.removeEventListener('resize', onResizeElem.checkForChanges);
onResizeElem.observer.disconnect();

0
jQuery(document).ready( function($) {

function resizeMapDIVs() {

// check the parent value...

var size = $('#map').parent().width();



if( $size < 640 ) {

//  ...and decrease...

} else {

//  ..or increase  as necessary

}

}

resizeMapDIVs();

$(window).resize(resizeMapDIVs);

});

0

ใช้Bharat Patilเพียงแค่ส่งกลับเท็จภายในการโทรกลับผูกของคุณเพื่อป้องกันข้อผิดพลาดสแต็คสูงสุดดูตัวอย่างด้านล่าง:

$('#test_div').bind('resize', function(){
   console.log('resized');
   return false;
});

0

นี่เป็นคำถามที่เก่ามาก แต่ฉันคิดว่าฉันโพสต์วิธีการแก้ปัญหาของฉันนี้

ฉันพยายามที่จะใช้ResizeSensorเพราะทุกคนดูเหมือนจะมีรอยย่นขนาดใหญ่บนมัน แม้ว่าจะนำมาใช้แล้วฉันก็ตระหนักว่าภายใต้ฝากระโปรง Element Query ต้องการองค์ประกอบที่เป็นปัญหาเพื่อให้ได้ตำแหน่งrelativeหรือabsoluteนำไปใช้กับสิ่งนั้นซึ่งไม่ได้ผลกับสถานการณ์ของฉัน

ฉันลงเอยด้วยการจัดการกับ Rxjs intervalแทนการใช้งานแบบตรงsetTimeoutหรือrequestAnimationFrameเหมือนก่อนหน้านี้

มีอะไรที่ดีเกี่ยวกับรสชาติที่สังเกตได้ของช่วงเวลานั้นคือคุณจะได้รับการปรับเปลี่ยนกระแสข้อมูลอย่างไรก็ตามสิ่งอื่นใดที่สามารถจัดการได้ สำหรับฉันแล้วการใช้งานขั้นพื้นฐานก็เพียงพอแล้ว แต่คุณอาจคลั่งและทำทุกอย่างได้เช่นกัน

ในตัวอย่างด้านล่างฉันกำลังติดตามการเปลี่ยนแปลงความกว้างของ div (สีเขียว) มีความกว้างตั้งไว้ที่ 50% แต่ความกว้างสูงสุด 200px การลากแถบเลื่อนจะส่งผลต่อความกว้างของตัวตัด (สีเทา) div คุณจะเห็นว่าสิ่งที่สังเกตได้นั้นจะเกิดขึ้นก็ต่อเมื่อความกว้างของ div ภายในเปลี่ยนไปซึ่งจะเกิดขึ้นหากความกว้างของ div ภายนอกน้อยกว่า 400px

const { interval } = rxjs;
const { distinctUntilChanged, map, filter } = rxjs.operators;


const wrapper = document.getElementById('my-wrapper');
const input = document.getElementById('width-input');




function subscribeToResize() {
  const timer = interval(100);
  const myDiv = document.getElementById('my-div');
  const widthElement = document.getElementById('width');
  const isMax = document.getElementById('is-max');
  
  /*
    NOTE: This is the important bit here 
  */
  timer
    .pipe(
      map(() => myDiv ? Math.round(myDiv.getBoundingClientRect().width) : 0),
      distinctUntilChanged(),
      // adding a takeUntil(), here as well would allow cleanup when the component is destroyed
    )
      .subscribe((width) => {        
        widthElement.innerHTML = width;
        isMax.innerHTML = width === 200 ? 'Max width' : '50% width';

      });
}

function defineRange() {
  input.min = 200;
  input.max = window.innerWidth;
  input.step = 10;
  input.value = input.max - 50;
}

function bindInputToWrapper() {
  input.addEventListener('input', (event) => {
    wrapper.style.width = `${event.target.value}px`;
  });
}

defineRange();
subscribeToResize();
bindInputToWrapper();
.inner {
  width: 50%;
  max-width: 200px;
}




/* Aesthetic styles only */

.inner {
  background: #16a085;
}

.wrapper {
  background: #ecf0f1;
  color: white;
  margin-top: 24px;
}

.content {
  padding: 12px;
}

body {
  
  font-family: sans-serif;
  font-weight: bold;
}
<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>

<h1>Resize Browser width</h1>

<label for="width-input">Adjust the width of the wrapper element</label>
<div>
  <input type="range" id="width-input">
</div>

<div id="my-wrapper" class="wrapper">
  <div id="my-div" class="inner">
    <div class="content">
      Width: <span id="width"></span>px
      <div id="is-max"></div>  
    </div>
  </div>
</div>


-1

เฉพาะWindow.onResizeที่มีอยู่ในสเปค แต่คุณสามารถใช้IFrameเพื่อสร้างใหม่Windowวัตถุภายใน div ของคุณ

โปรดตรวจสอบคำตอบนี้ มีปลั๊กอิน jqueryใหม่เล็ก ๆ น้อย ๆที่พกพาได้และใช้งานง่าย คุณสามารถตรวจสอบซอร์สโค้ดได้เสมอเพื่อดูว่ามันเสร็จสิ้นแล้ว

<!-- (1) include plugin script in a page -->
<script src="/src/jquery-element-onresize.js"></script>

// (2) use the detectResizing plugin to monitor changes to the element's size:
$monitoredElement.detectResizing({ onResize: monitoredElement_onResize });

// (3) write a function to react on changes:
function monitoredElement_onResize() {    
    // logic here...
}

นี่เป็นวิธีที่ไม่ได้ผลอย่างมากหากคุณมี div ที่ปรับขนาดได้
suricactus

-1

ฉันคิดว่ามันไม่สามารถทำได้ แต่จากนั้นฉันคิดเกี่ยวกับมันคุณสามารถปรับขนาด div ด้วยตนเองผ่าน style = "ปรับขนาด: ทั้งคู่;" เพื่อที่จะทำเช่นนั้นคุณต้องคลิกเพื่อเพิ่มฟังก์ชั่น onclick เพื่อตรวจสอบความสูงและความกว้างขององค์ประกอบและใช้งานได้ ด้วยจาวาสคริปต์ที่บริสุทธิ์เพียง 5 บรรทัด (แน่นอนว่าอาจสั้นกว่านี้) http://codepen.io/anon/pen/eNyyVN

<div id="box" style="
                height:200px; 
                width:640px;
                background-color:#FF0066;
                resize: both;
                overflow: auto;" 
                onclick="myFunction()">
    <p id="sizeTXT" style="
                font-size: 50px;">
       WxH
    </p>
    </div>

<p>This my example demonstrates how to run a resize check on click for resizable div.</p>

<p>Try to resize the box.</p>


<script>
function myFunction() {
var boxheight = document.getElementById('box').offsetHeight;
var boxhwidth = document.getElementById('box').offsetWidth;
var txt = boxhwidth +"x"+boxheight;
document.getElementById("sizeTXT").innerHTML = txt;
}
</script>

2
สิ่งนี้จะคำนวณเฉพาะเมื่อมีการคลิกเหตุการณ์ซึ่งไม่ได้เป็นส่วนหนึ่งของข้อกำหนดของคำถาม
Rob Evans
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.