Чи можливо виявити, використовуючи JavaScript, коли користувач змінює масштаб сторінки? Я просто хочу зловити подію "масштабування" та відповісти на неї (подібно до події window.onresize).
Дякую.
Чи можливо виявити, використовуючи JavaScript, коли користувач змінює масштаб сторінки? Я просто хочу зловити подію "масштабування" та відповісти на неї (подібно до події window.onresize).
Дякую.
Відповіді:
Немає можливості активно визначати наявність масштабу. Тут я знайшов хороший запис про те, як можна спробувати його реалізувати.
Я знайшов два способи виявлення рівня збільшення. Один із способів виявлення змін рівня масштабування покладається на той факт, що відсоткові значення не збільшуються. Значення у відсотках є відносно ширини вікна перегляду, і, таким чином, не впливає масштаб сторінки. Якщо ви вставите два елементи, один із позицією у відсотках, а другий із однаковою позицією у пікселях, вони будуть розсуватися, коли сторінка збільшується. Знайдіть співвідношення позицій обох елементів, і ви отримали рівень масштабування. Дивіться тестовий випадок. http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
Ви також можете це зробити, використовуючи інструменти вищезгаданої публікації. Проблема полягає в тому, що ви в більшій чи меншій мірі пропонуєте освічені здогадки про те, чи збільшила сторінку чи ні. Це буде працювати в деяких браузерах краще, ніж в інших.
Немає способу визначити, чи збільшена сторінка, якщо вони завантажують вашу сторінку під час збільшення.
document.body.offsetWidth
Я використовую цей фрагмент JavaScript, щоб реагувати на масштабування "подій".
Він опитує ширину вікна. (Як дещо пропонується на цій сторінці (до якої посилається Іан Еліотт): http://novemberborn.net/javascript/page-zoom-ff3 [архів] )
Тестовано з Chrome, Firefox 3.6 та Opera, а не IE.
З повагою, Магнус
var zoomListeners = [];
(function(){
// Poll the pixel width of the window; invoke zoom listeners
// if the width has been changed.
var lastWidth = 0;
function pollZoomFireEvent() {
var widthNow = jQuery(window).width();
if (lastWidth == widthNow) return;
lastWidth = widthNow;
// Length changed, user must have zoomed, invoke listeners.
for (i = zoomListeners.length - 1; i >= 0; --i) {
zoomListeners[i]();
}
}
setInterval(pollZoomFireEvent, 100);
})();
Гарні новини всідеякі люди! Більш нові браузери запускають подію зміни розміру вікна при зміні масштабу.
Давайте визначимо px_ratio як нижче:
px співвідношення = відношення фізичного пікселя до css px.
якщо будь-який масштаб Сторінка, pxes вікна перегляду (px відрізняється від пікселя) зменшується і має бути придатним до екрана, тому співвідношення (фізичний піксель / CSS_px) повинно збільшуватися.
але у розмірі вікна розмір екрана зменшується, а також pxes. тому співвідношення збережеться.
але
зміна розміру: тригер Windows.resize подія -> не змінює px_ratio
//for zoom detection
px_ratio = window.devicePixelRatio || window.screen.availWidth / document.documentElement.clientWidth;
$(window).resize(function(){isZooming();});
function isZooming(){
var newPx_ratio = window.devicePixelRatio || window.screen.availWidth / document.documentElement.clientWidth;
if(newPx_ratio != px_ratio){
px_ratio = newPx_ratio;
console.log("zooming");
return true;
}else{
console.log("just resizing");
return false;
}
}
Ключовим моментом є різниця між CSS PX та Physical Pixel.
https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e
Існує чудовий плагін, вбудований з yonran
якого може виявити. Ось його відповідь, що раніше відповідав на StackOverflow. Він працює для більшості браузерів. Застосування так само просто:
window.onresize = function onresize() {
var r = DetectZoom.ratios();
zoomLevel.innerHTML =
"Zoom level: " + r.zoom +
(r.zoom !== r.devicePxPerCssPx
? "; device to CSS pixel ratio: " + r.devicePxPerCssPx
: "");
}
Always enable zoom
кнопку в опції Accessibility. Демонстрація не реагує на зміну.
Я хотів би запропонувати покращити попереднє рішення із відстеженням змін ширини вікна. Замість того, щоб зберігати власний масив слухачів подій, ви можете використовувати існуючу систему подій javascript і запускати власну подію при зміні ширини та прив’язувати до неї обробники подій.
$(window).bind('myZoomEvent', function() { ... });
function pollZoomFireEvent()
{
if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}
Дросель / дебютація може допомогти зменшити кількість дзвінків вашого обробника.
Ви також можете отримати події зміни розміру тексту та коефіцієнт збільшення, ввівши div, що містить принаймні нерозривний пробіл (можливо, прихований), і регулярно перевіряючи його висоту. Якщо висота змінюється, розмір тексту змінився, (і ви знаєте, на скільки - це також спрацьовує, до речі, якщо вікно збільшується в повноекранному режимі, і ви все одно отримаєте правильний коефіцієнт масштабування з однаковою висотою / коефіцієнт висоти).
<script>
var zoomv = function() {
if(topRightqs.style.width=='200px){
alert ("zoom");
}
};
zoomv();
</script>
На iOS 10 можна додати слухача події до touchmove
події та виявити, якщо сторінка масштабується поточною подією.
var prevZoomFactorX;
var prevZoomFactorY;
element.addEventListener("touchmove", (ev) => {
let zoomFactorX = document.documentElement.clientWidth / window.innerWidth;
let zoomFactorY = document.documentElement.clientHeight / window.innerHeight;
let pageHasZoom = !(zoomFactorX === 1 && zoomFactorY === 1);
if(pageHasZoom) {
// page is zoomed
if(zoomFactorX !== prevZoomFactorX || zoomFactorY !== prevZoomFactorY) {
// page is zoomed with this event
}
}
prevZoomFactorX = zoomFactorX;
prevZoomFactorY = zoomFactorY;
});
Хоча це вже 9 років питання, проблема не зникає!
Я виявляв розмір, виключаючи масштабування в проекті, тому я відредагував свій код, щоб він міг визначати як розмір, так і масштаб виключно один від одного. Він працює більшу частину часу, тому якщо більшість достатньо хороших для вашого проекту, то це має бути корисним! Він виявляє масштабування 100% часу в тому, що я тестував до цих пір. Єдине питання полягає в тому, що якщо користувач божеволіє (тобто просторово змінює розмір вікна) або вікно відстає, воно може спрацювати як масштаб замість розміру вікна.
Він працює шляхом виявлення зміни window.outerWidth
або window.outerHeight
зміни розміру вікна під час виявлення зміни window.innerWidth
або window.innerHeight
незалежної від зміни розміру вікна як збільшення.
//init object to store window properties
var windowSize = {
w: window.outerWidth,
h: window.outerHeight,
iw: window.innerWidth,
ih: window.innerHeight
};
window.addEventListener("resize", function() {
//if window resizes
if (window.outerWidth !== windowSize.w || window.outerHeight !== windowSize.h) {
windowSize.w = window.outerWidth; // update object with current window properties
windowSize.h = window.outerHeight;
windowSize.iw = window.innerWidth;
windowSize.ih = window.innerHeight;
console.log("you're resizing"); //output
}
//if the window doesn't resize but the content inside does by + or - 5%
else if (window.innerWidth + window.innerWidth * .05 < windowSize.iw ||
window.innerWidth - window.innerWidth * .05 > windowSize.iw) {
console.log("you're zooming")
windowSize.iw = window.innerWidth;
}
}, false);
Примітка. Моє рішення схоже на рішення KajMagnus, але це працювало краще для мене.
0.05
не надаючи принаймні гарного пояснення. ;-) Наприклад, я знаю, що в Chrome, зокрема, 10% - це найменша сума, яку браузер збільшуватиме в будь-якому випадку, але не зрозуміло, що це стосується інших браузерів. fyi, завжди переконайтесь, що ваш код перевірений, і будьте готові захищати чи вдосконалювати його.
Ось чисте рішення:
// polyfill window.devicePixelRatio for IE
if(!window.devicePixelRatio){
Object.defineProperty(window,'devicePixelRatio',{
enumerable: true,
configurable: true,
get:function(){
return screen.deviceXDPI/screen.logicalXDPI;
}
});
}
var oldValue=window.devicePixelRatio;
window.addEventListener('resize',function(e){
var newValue=window.devicePixelRatio;
if(newValue!==oldValue){
// TODO polyfill CustomEvent for IE
var event=new CustomEvent('devicepixelratiochange');
event.oldValue=oldValue;
event.newValue=newValue;
oldValue=newValue;
window.dispatchEvent(event);
}
});
window.addEventListener('devicepixelratiochange',function(e){
console.log('devicePixelRatio changed from '+e.oldValue+' to '+e.newValue);
});
Подія зміни розміру працює в сучасних браузерах, приєднуючи подію до window
, а потім читаючи значення body
або іншого елемента за допомогою, наприклад, .getBoundingClientRect () ).
У деяких попередніх браузерах можна було зареєструвати обробники змін розміру на будь-якому HTML-елементі. Ще можна встановити атрибути onresize або використовувати addEventListener () для встановлення обробника будь-якого елемента. Однак події зміни розміру запускаються лише на об’єкт вікна (тобто повертаються document.defaultView). Тільки обробники, зареєстровані на об'єкті вікна, отримуватимуть події зміни розміру .
window.addEventListener("resize", getSizes, false)
function getSizes(){
let body = document.body
console.log(body.clientWidth +"px x "+ body.clientHeight + "px")
}
Інша альтернатива : API ResizeObserver
Залежно від вашого макета, ви можете спостерігати за зміною розміру певного елемента.
Це добре працює на «чуйних» макетів, оскільки контейнер розміру змінюється під час збільшення.
function watchBoxchange(e){
// console.log(e[0].contentBoxSize.inlineSize+" "+e[0].contentBoxSize.blockSize)
info.textContent = e[0].contentBoxSize.inlineSize+" * "+e[0].contentBoxSize.blockSize + "px"
}
new ResizeObserver(watchBoxchange).observe(fluid)
#fluid {
width: 200px;
height:100px;
overflow: auto;
resize: both;
border: 3px black solid;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 8vh
}
<div id="fluid">
<info id="info"></info>
</div>
Будьте обережні, щоб не перевантажувати завдання javascript від подій жестів користувачів. Використовуйте requestAnimationFrame, коли вам потрібно перемальовувати.
Згідно з MDN, "matchMedia" - це правильний спосіб зробити це https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes
це трохи вибагливо, тому що кожен екземпляр може переглядати лише один MQ одночасно, тому якщо вас цікавить будь-яке зміна рівня масштабування, вам потрібно зробити купу відповідників .. але оскільки браузер відповідає за видачу подій, можливо все-таки ефективніше, ніж опитування, і ви можете придушити або зняти зворотний дзвінок або прив’язати його до анімаційного кадру чи чогось іншого - ось реалізація, яка здається досить спритною, не соромтеся поміняти _throttle або що завгодно, якщо ви вже залежаєте від цього.
Запустіть фрагмент коду та збільшить масштаб у своєму браузері, відзначте оновлене значення у розмітці - це я протестував лише у Firefox! знаю, якщо ви бачите якісь проблеми.
const el = document.querySelector('#dppx')
if ('matchMedia' in window) {
function observeZoom(cb, opts) {
opts = {
// first pass for defaults - range and granularity to capture all the zoom levels in desktop firefox
ceiling: 3,
floor: 0.3,
granularity: 0.05,
...opts
}
const precision = `${opts.granularity}`.split('.')[1].length
let val = opts.floor
const vals = []
while (val <= opts.ceiling) {
vals.push(val)
val = parseFloat((val + opts.granularity).toFixed(precision))
}
// construct a number of mediamatchers and assign CB to all of them
const mqls = vals.map(v => matchMedia(`(min-resolution: ${v}dppx)`))
// poor person's throttle
const throttle = 3
let last = performance.now()
mqls.forEach(mql => mql.addListener(function() {
console.debug(this, arguments)
const now = performance.now()
if (now - last > throttle) {
cb()
last = now
}
}))
}
observeZoom(function() {
el.innerText = window.devicePixelRatio
})
} else {
el.innerText = 'unable to observe zoom level changes, matchMedia is not supported'
}
<div id='dppx'>--</div>
Я відповідаю на трирічне посилання, але, мабуть, ось більш прийнятна відповідь,
Створіть .css файл як,
@media screen and (max-width: 1000px)
{
// things you want to trigger when the screen is zoomed
}
EG: -
@media screen and (max-width: 1000px)
{
.classname
{
font-size:10px;
}
}
Вищевказаний код робить розмір шрифту '10px', коли екран збільшується приблизно до 125%. Ви можете перевірити різний рівень масштабування, змінивши значення "1000px".
max-width
та коефіцієнтом збільшення?