Странное поведение getBoundingClientRect() и F5/перезагрузка, что происходит?

#javascript #html #css

Вопрос:

Мои извинения за длинный код, я раздевался, раздевался и снова раздевался. Codepen по природе этого вопроса бесполезен. Я сделал код полностью автономным, вы можете просто вырезать и вставить его в html-файл, чтобы увидеть поведение.

 <!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Garden</title>
</head>
<body>
<style>

#page {      
    display: inline-grid;
    grid-template-columns:auto;
    grid-template-rows: 3;
    grid-template-areas: 
    "header"
    "map"
    "footer";
}
  
#header {       
    grid-area: header;
    color: white;
    background-color: grey;
    border: 2px solid grey;
    border-bottom: none;
    border-radius: 10px 10px 0px 0px;   
    padding: 5px;  
}

#map {   
    grid-area: map;
    border: 2px solid grey;
    border-top: none;
    padding: 5px;
}   

#imagewrapper {    
    position: relative;
    border: 1px solid grey;
    padding: none;
    margin: none;
}

#mapimage { 
    display: inline;
    max-width: 100%;
    margin-bottom: -4px;
}

.pin_container {
    
    position: absolute;
    border: 2px solid grey;
    border-radius: 10px 10px 10px 10px;
    cursor: grab;
    padding: 3px;
}

#footer {
    grid-area: footer;
    color: white;
    background-color: grey;
    border: 2px solid grey;
    border-right: none;
    border-radius: 0px 0px 10px 10px;   
    padding: 5px;  
}
</style>
<div id='page'>
    <div id='header'>De Botanische Tuin Kerkrade</div>
    <div id='map' data-id='14'>
        <div id='imagewrapper'>
            <img id='mapimage' src='https://i.ibb.co/cQF07s8/map-g3-v1.png'>
            <div id='b27' class='pin_container' style='left:479px; top:792px;' data-img='map_g3_b27_v0.png'>Hubertus Borders</div>
            <div id='b22' class='pin_container' style='left:385px; top:568px;' data-img='map_g3_b22_v0.png'>De Oude Tuin</div>
            <div id='b9' class='pin_container' style='left:400px; top:400px;' data-img='map_g3_b9_v0.png'>De Thematuin</div>
        </div>
    </div>
    <div id='footer'><span class='nav_current'>De Botanische Tuin Kerkrade</span></div>
</div>

<script type="text/javascript">

    var map  = document.getElementById('imagewrapper').getBoundingClientRect();
    var pins = document.querySelectorAll('.pin_container');
    var pin;
    var div;
    var loc_x;
    var loc_y;

    for ( var i = 0; i < pins.length; i   ) { 
        
        pin    = pins[i];
        div    = pin.getBoundingClientRect();
     
        console.log( pin.textContent "(" pin.id ") - imagewrapper.width=" map.width ", pin_container.width=" div.width );
    }
</script>
</body>
</html>
 

В любом случае, я использую js для центрирования divs с классом «pin_container» на «imagewrapper». Размер обертки изображения определяется содержащимся в ней изображением, которое установлено на 100%, поэтому я могу легко масштабировать его, когда окно просмотра становится меньше, чем карта.
Если я загружаю страницу, я регистрирую это в консоли, и это нормально (синяя линия на карте имеет ширину 100 пикселей).:

 Hubertus Borders(b27) - imagewrapper.width=707, pin_container.width=123.33
De Oude Tuin(b22) - imagewrapper.width=707, pin_container.width=100.96
De Thematuin(b9) - imagewrapper.width=707, pin_container.width=101.96
 

Однако, если я обновлю страницу, я получу это:

 Hubertus Borders(b27) - imagewrapper.width=190.93333435058594, pin_container.width=68.66
De Oude Tuin(b22) - imagewrapper.width=190.93333435058594, pin_container.width=44.64
De Thematuin(b9) - imagewrapper.width=190.93333435058594, pin_container.width=79.31
 

Как вы можете видеть, ширина как карты, так и булавок сейчас просто чушь собачья.
Прежде чем я раздел этот код до костей, я получил еще другие результаты, если использовал ctrl f5. К сожалению, я не могу найти, какой фрагмент кода вызвал такое поведение.
Я проверил Chrome, Firefox standard и разработчика. Две лисы ведут себя так, как описано выше, Chrome постоянно выдает мне неверный вывод, независимо от того, загружаю ли я новую нагрузку или что-то в этом роде с F5.

Имейте в виду, что результирующий рендеринг-это то, чего я ожидал бы от правильного вывода, независимо от того, какой браузер или действие я использую. Однако это портит сценарий центрирования, который использует getBoundingClientRect().

Что здесь происходит?

Комментарии:

1. Я не могу воспроизвести проблему со своей стороны, но что-то подсказывает мне, что проблема в коде, выполненном до полной загрузки изображения.

2. Это то, о чем я тоже подумал в первую очередь, но в теге de image нет ничего особенного, размер изображения не так уж велик, и я тестирую его локально со всеми файлами на твердотельном накопителе. Итак, если эта настройка не загружает изображение достаточно быстро для этого сценария, что происходит?

Ответ №1:

Проблема не в том, что изображение загружается поздно или, по крайней мере, оно вызывает его косвенно.

для воспроизведения просто запустите цикл в предоставленном коде во второй раз в консоли.


Это скорее объяснение, чем ответ.

Мы имеем дело с абсолютно позиционированными элементами, абсолютно позиционированные не имеют измерений, они зависят от их содержимого, в данном случае это текст, Текст непредсказуем.

При применении позиционирования позиционируемого элемента с использованием четырех свойств он перестанет двигаться, когда достигнет одного из ребер, и начнет уменьшаться, а не двигаться, пока не достигнет предела, который является самым длинным словом.

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

Решением было бы определить ширину/высоту для ваших расположенных элементов или, возможно, white-space:nowrap

я не уверен, как будет масштабироваться ваше приложение, поэтому я не могу дать постоянного решения, определение ширины/высоты может быть нежелательным

Комментарии:

1. Я понимаю, к чему вы клоните, но почему это происходит, когда я нажимаю F5, но не когда страница загружается с закладки или ссылки? У меня почти такая же настройка для размещения контактов, но в этом случае изображение добавляется в качестве фона в div imagewrapper (так как мне не нужно изменять размер карты). Не вижу проблемы, когда я использую ту же функцию js для центрирования контактов. Похоже, что изменение размера карт причиняет мне много боли. 🙁

2. Я понятия не имею, я не могу воспроизвести это так же, как вы. Так что в вашей настройке есть что-то другое, я бы предположил, что проблема с кэшированием, но даже отключение кэша дает те же результаты

3. Странно, странно, странно. Это действительно была загрузка, которая вызвала проблемы. Я поставил задержку в 1 мс в коде, и затем это сработало, если только я не принудительно обновил кэш. В конце концов я просто добавил ширину карты в пикселях к тегу изображения, что все решило. Теперь я задаюсь вопросом, почему изображение все еще изменяется, когда видовое окно становится меньше, чем изображение, но это другой вопрос. Спасибо, что помогли мне двигаться вперед, @Zohir Salak!

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

5. @ZohirSalak Сначала вы говорите, что задержка загрузки изображения не является причиной, но вы говорите, что это вызвано тем, что изображение еще не загружено, если родительское поле имеет другой размер, пока оно не загружено. Какой из них лучше?