Как определить уровень масштабирования страницы во всех современных браузерах? - PullRequest
290 голосов
/ 11 ноября 2009
  1. Как определить уровень масштабирования страницы во всех современных браузерах? Хотя этот поток рассказывает, как это сделать в IE7 и IE8, я не могу найти хорошее кросс-браузерное решение.

  2. Firefox сохраняет уровень масштабирования страницы для последующего доступа. Смогу ли я получить уровень масштабирования при загрузке первой страницы? Где-то я читал, что это работает, когда изменение масштаба происходит после страница загружена.

  3. Есть ли способ перехватить событие 'zoom'?

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


Модифицированный образец, заданный @ tfl

Эта страница предупреждает о различных значениях высоты при увеличении. [jsFiddle]

<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js" type="text/javascript"/></script>
    </head>
    <body>
        <div id="xy" style="border:1px solid #f00; width:100px;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque sollicitudin tortor in lacus tincidunt volutpat. Integer dignissim imperdiet mollis. Suspendisse quis tortor velit, placerat tempor neque. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent bibendum auctor lorem vitae tempor. Nullam condimentum aliquam elementum. Nullam egestas gravida elementum. Maecenas mattis molestie nisl sit amet vehicula. Donec semper tristique blandit. Vestibulum adipiscing placerat mollis.</div>
        <button onclick="alert($('#xy').height());">Show</button>
    </body>
</html>

Ответы [ 25 ]

265 голосов
/ 22 февраля 2011

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

Редактировать (2011-12-12): Я добавил проект, который можно клонировать: https://github.com/tombigel/detect-zoom

  • IE8 : screen.deviceXDPI / screen.logicalXDPI (или, для уровня масштабирования относительно масштаба по умолчанию, screen.systemXDPI / screen.logicalXDPI)
  • IE7 : var body = document.body,r = body.getBoundingClientRect(); return (r.left-r.right)/body.offsetWidth; (спасибо этому примеру или этому ответу )
  • ТОЛЬКО FF3.5 : screen.width / ширина экрана медиа-запроса (см. Ниже) (используется тот факт, что screen.width использует пиксели устройства, но ширина MQ использует пиксели CSS - благодаря Ширина причуда )
  • FF3,6 : неизвестный метод
  • FF4 + : бинарный поиск в медиа-запросах (см. Ниже)
  • WebKit : https://www.chromestatus.com/feature/5737866978131968 (спасибо Тео в комментариях)
  • WebKit : измерьте предпочтительный размер div с помощью -webkit-text-size-adjust:none.
  • WebKit : (не работает с r72591 ) document.width / jQuery(document).width() (благодаря Дирк ван Остербош выше ). Чтобы получить соотношение в пикселях устройства (вместо относительного увеличения по умолчанию), умножьте на window.devicePixelRatio.
  • Старый WebKit? (не проверено): parseInt(getComputedStyle(document.documentElement,null).width) / document.documentElement.clientWidth (из этот ответ )
  • Опера : document.documentElement.offsetWidth / ширина position:fixed; width:100% дел. отсюда ( Таблица ширины Quirksmode говорит, что это ошибка; innerWidth должен быть CSS px). Мы используем элемент position: fixed, чтобы получить ширину области просмотра , включая пространство, где полосы прокрутки ; document.documentElement.clientWidth исключает эту ширину. Это сломано с 2011 года; Я больше не знаю, как получить уровень масштабирования в Opera.
  • Другое : Flash-решение от Себастьяна
  • Ненадежно: слушать события мыши и измерять изменения в screenX / изменения в clientX

Вот бинарный поиск для Firefox 4, так как я не знаю ни одной переменной, где он выставлен:

<style id=binarysearch></style>
<div id=dummyElement>Dummy element to test media queries.</div>
<script>
var mediaQueryMatches = function(property, r) {
  var style = document.getElementById('binarysearch');
  var dummyElement = document.getElementById('dummyElement');
  style.sheet.insertRule('@media (' + property + ':' + r +
                         ') {#dummyElement ' +
                         '{text-decoration: underline} }', 0);
  var matched = getComputedStyle(dummyElement, null).textDecoration
      == 'underline';
  style.sheet.deleteRule(0);
  return matched;
};
var mediaQueryBinarySearch = function(
    property, unit, a, b, maxIter, epsilon) {
  var mid = (a + b)/2;
  if (maxIter == 0 || b - a < epsilon) return mid;
  if (mediaQueryMatches(property, mid + unit)) {
    return mediaQueryBinarySearch(
        property, unit, mid, b, maxIter-1, epsilon);
  } else {
    return mediaQueryBinarySearch(
        property, unit, a, mid, maxIter-1, epsilon);
  }
};
var mozDevicePixelRatio = mediaQueryBinarySearch(
    'min--moz-device-pixel-ratio', '', a, b, maxIter, epsilon);
var ff35DevicePixelRatio = screen.width / mediaQueryBinarySearch(
    'min-device-width', 'px', 0, 6000, 25, .0001);
</script>
45 голосов
/ 16 июня 2011

Для меня, для Chrome / Webkit, document.width / jQuery(document).width() не работал. Когда я сделал окно маленьким и увеличил его, чтобы появились горизонтальные полосы прокрутки, document.width / jQuery(document).width() не равнялся 1 при увеличении по умолчанию. Это связано с тем, что document.width включает часть документа вне области просмотра.

Использование window.innerWidth и window.outerWidth сработало. По какой-то причине в Chrome externalWidth измеряется в пикселях экрана, а innerWidth измеряется в пикселях CSS.

var screenCssPixelRatio = (window.outerWidth - 8) / window.innerWidth;
if (screenCssPixelRatio >= .46 && screenCssPixelRatio <= .54) {
  zoomLevel = "-4";
} else if (screenCssPixelRatio <= .64) {
  zoomLevel = "-3";
} else if (screenCssPixelRatio <= .76) {
  zoomLevel = "-2";
} else if (screenCssPixelRatio <= .92) {
  zoomLevel = "-1";
} else if (screenCssPixelRatio <= 1.10) {
  zoomLevel = "0";
} else if (screenCssPixelRatio <= 1.32) {
  zoomLevel = "1";
} else if (screenCssPixelRatio <= 1.58) {
  zoomLevel = "2";
} else if (screenCssPixelRatio <= 1.90) {
  zoomLevel = "3";
} else if (screenCssPixelRatio <= 2.28) {
  zoomLevel = "4";
} else if (screenCssPixelRatio <= 2.70) {
  zoomLevel = "5";
} else {
  zoomLevel = "unknown";
}
44 голосов
/ 14 июня 2016

Вы можете попробовать

var browserZoomLevel = Math.round(window.devicePixelRatio * 100);

Это даст вам процент увеличения масштаба браузера.

Чтобы поймать событие масштабирования, вы можете использовать

$(window).resize(function() { 
// your code 
});
16 голосов
/ 18 апреля 2013

Мой коллега и я использовали скрипт из https://github.com/tombigel/detect-zoom. Кроме того, мы также динамически создали элемент svg и проверили его свойство currentScale. Он отлично работает на Chrome и, вероятно, на большинстве браузеров. На FF функция «только масштабирование текста» должна быть отключена. SVG поддерживается в большинстве браузеров. На момент написания статьи проверено на IE10, FF19 и Chrome28.

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
svg.setAttribute('version', '1.1');
document.body.appendChild(svg);
var z = svg.currentScale;
... more code ...
document.body.removeChild(svg);
11 голосов
/ 09 мая 2016
zoom = ( window.outerWidth - 10 ) / window.innerWidth

Это все, что тебе нужно.

11 голосов
/ 07 ноября 2011

Я нашел эту статью чрезвычайно полезной. Огромное спасибо Йонрану. Я хотел пройти некоторое дополнительное обучение, которое я нашел, внедряя некоторые из методов, которые он предоставил. В FF6 и Chrome 9 была добавлена ​​поддержка медиазапросов из JS, что может значительно упростить подход к медиазапросам, необходимый для определения масштабирования в FF. См. Документы в MDN здесь . Для моих целей мне нужно было только определить, был ли браузер увеличен или уменьшен, мне не требовался фактический коэффициент увеличения. Мне удалось получить ответ с одной строкой JavaScript:

var isZoomed = window.matchMedia('(max--moz-device-pixel-ratio:0.99), (min--moz-device-pixel-ratio:1.01)').matches;

Объединив это с решениями IE8 + и Webkit, которые также представляли собой одну строку, я смог обнаружить увеличение масштаба в большинстве браузеров, попавших в наше приложение с помощью всего нескольких строк кода.

6 голосов
/ 19 января 2017

У меня есть решение для этого по состоянию на январь 2016 года. Протестировано в браузерах Chrome, Firefox и MS Edge.

Принцип заключается в следующем. Соберите 2 очка MouseEvent, которые находятся далеко друг от друга. Каждое событие мыши имеет экран и координаты документа. Измерьте расстояние между двумя точками в обеих системах координат. Несмотря на то, что из-за мебели браузера существуют переменные фиксированные смещения между системами координат, расстояние между точками должно быть одинаковым, если страница не масштабирована. Причиной указания «далеко друг от друга» (я назвал это 12 пикселями) является то, что обнаруживаются небольшие изменения масштаба (например, 90% или 110%).

Ссылка: https://developer.mozilla.org/en/docs/Web/Events/mousemove

Шаги:

  1. Добавить слушателя перемещения мыши

    window.addEventListener("mousemove", function(event) {
        // handle event
    });
    
  2. Захват 4 измерений от событий мыши:

    event.clientX, event.clientY, event.screenX, event.screenY
    
  3. Измерьте расстояние d_c между двумя точками в клиентской системе

  4. Измерьте расстояние d_s между двумя точками в системе экранов

  5. Если d_c! = D_s, то применяется масштабирование. Разница между ними говорит о величине увеличения.

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

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

3 голосов
/ 21 марта 2013

Это отлично работает для меня в браузерах на основе webkit (Chrome, Safari):

function isZoomed() {
    var width, mediaQuery;

    width = document.body.clientWidth;
    mediaQuery = '(max-width: ' + width + 'px) and (min-width: ' + width + 'px)';

    return !window.matchMedia(mediaQuery).matches;
}

Похоже, что не работает в Firefox.

Это также работает в WebKit:

var zoomLevel = document.width / document.body.clientWidth;
3 голосов
/ 08 декабря 2010

В Internet Explorer 7, 8 и 9 это работает:

function getZoom() {
    var screen;

    screen = document.frames.screen;
    return ((screen.deviceXDPI / screen.systemXDPI) * 100 + 0.9).toFixed();
}

"+0,9" добавлено для предотвращения ошибок округления (в противном случае вы получите 104% и 109%, если масштаб браузера установлен на 105% и 110% соответственно).

В IE6 масштабирования не существует, поэтому нет необходимости проверять масштаб.

3 голосов
/ 12 июня 2013

Что я придумал, это:

1) Сделайте position:fixed <div> с width:100% ( id = zoomdiv )

2) при загрузке страницы:

zoomlevel=$("#zoomdiv").width()*1.0 / screen.availWidth

И у меня это сработало для ctrl+ и ctrl- увеличения.

или я могу добавить строку к событию $(window).onresize(), чтобы получить активный уровень масштабирования


Код:

<script>
    var zoom=$("#zoomdiv").width()*1.0 / screen.availWidth;

    $(window).resize(function(){
        zoom=$("#zoomdiv").width()*1.0 / screen.availWidth;
        alert(zoom);    
    });
</script>
<body>
    <div id=zoomdiv style="width:100%;position:fixed;"></div>
</body>

P.S. : это мой первый пост, простите за любые ошибки

...