Обнаружение изменения размера элемента, инициированного пользователем (в отличие от изменения размера потока документов) - PullRequest
0 голосов
/ 27 марта 2020

Мне нужен iframe, который занимает все доступное пространство по горизонтали и автоматически изменяет размеры по вертикали, чтобы соответствовать его содержимому (в том числе при изменении содержимого или изменении размера окна), но также может изменять размер вручную пользователем, используя свойство CSS resize: both. Цель состоит в том, чтобы встроить дизайн, по умолчанию заполняя доступное пространство, а также дать пользователю возможность увидеть, как он работает на экранах разных размеров.

Элемент iframe имеет одинаковое происхождение, поэтому проблем с безопасностью нет - родительское окно может делать все, что угодно, с iframe.contentDocument.

Автоматически изменить размер фрейма так, чтобы он соответствовал его содержимому, просто:

<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
        style="width:calc(100% - 2px);border:1px solid black"
        onload="
    recalculate = () => {
        this.style.height = this.contentDocument.documentElement.offsetHeight + 'px';
    }
    new ResizeObserver(recalculate).observe(this.contentDocument.documentElement);
    recalculate();
"></iframe>

(Вау, что HTML Подсветка синтаксиса там действительно развалилась! Кроме того, здесь нет правильного «фрагмента», потому что CSP, кажется, нарушает contentDocument доступ.)

И создание изменяемого пользователем iframe прямолинейно:

<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
        style="resize:both"></iframe>

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

Так что, если пользователь вручную изменяет размер iframe, я хочу, чтобы мое авто-изменение размера Чтобы отключить ResizeObserver.

Можно ли как-то отличить guish изменение размера из-за действий пользователя (изменение размера iframe с помощью углового адаптера) от изменения размера из-за изменения среды (изменение содержимого) внутри iframe или изменение макета без iframe, включая изменение размера области просмотра)?

1 Ответ

0 голосов
/ 27 марта 2020

При изменении размера вручную устанавливается element.style.{width, height}. Таким образом, одним из решений является автоматическое изменение размеров, чтобы не использовать эти свойства, а установить ширину и высоту другим способом, чтобы вы могли различать guish значения.

Для width , это легко, потому что авторазмер устанавливает только height: если установлено width (или, если вы установите значение, например calc(100% - 2px), установите что-то другое), отключите авторазмер.

для высоты? Это сложнее, но мне пришло в голову два метода:

  1. Установите высоту в отдельной таблице стилей (чтобы element.style.height вообще не задавалась) и продолжайте обновлять текст этого элемента стиля .
  2. Используйте height: var(--height) и установите --height на фактическое значение. Таким образом, element.style.height не изменится, пока не произойдет изменение размера пользователя. Я рекомендую эту технику, так как ее немного легче рассуждать, и я подозреваю, что она может быть немного быстрее (хотя я вообще не проверял это).
<style>
iframe {
    width: calc(100% - 2px);
    border: 1px solid black;
    resize: both;
}
</style>
<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
        style="height:var(--height)"
        onload="
    recalculate = () => {
        // (var(--height) could just as easily be shifted to the stylesheet,
        // but I’m demonstrating a point here in how it can be done.)
        if (this.style.width || this.style.height !== 'var(--height)') {
            // User resizing has occurred.
            if (observer) {
                observer.disconnect();
            }
            return;
        }
        this.style.setProperty('--height', this.contentDocument.documentElement.offsetHeight + 'px');
    }
    var observer = window.ResizeObserver && new ResizeObserver(recalculate);
    if (observer) {
        observer.observe(this.contentDocument.documentElement);
    }
    recalculate();
"></iframe>
...