Wykrywanie poziomu powiększenia w przeglądarce.
Gdybym za każdym razem, kiedy źródłem błędnego wyświetlania się strony jest to, że klient ma zwiększony poziom zbliżenia (Ctrl +) dostawał 5 zł miałbym już chyba na parę zgrzewek PEPSI ;-) Przy jednym z ostatnich mini projektów potrzebowałem informacji właśnie o tym - czy osoba odwiedzająca stronę ma ustawiony zoom na wartość inną niż 100%.
Pierwsze próby spełzły na niczym - myślałem, że przy zwiększeniu poziomu zoom-u wymiary obrazków pobierane dynamicznie przez JavaScript będą odzwierciedlał ich nowe proporcje - jednak tak nie jest, podają one wciąż rzeczywiste (ustalone na stronie za pomocą HTML/CSS) wymiary. Okazało się, że jedynym obiektem, który przy zmianie zoom-u potrafi zgłaszać swój nowy wymiar jest Flash. Nie przepadam za Flashem, ale Action Script mam jako-tako opanowany, więc całość zamknęła się w 8 linijkach AS3 i kilku JS. Zacznijmy od Action Script:
stage.scaleMode = "noScale"; #1
import flash.external.ExternalInterface;
import flash.utils.setInterval;
function sendSignal():void {
ExternalInterface.call("flashSize", stage.stageWidth); #5
}
setInterval(sendSignal, 100);
sendSignal();
Wyjaśnię tylko co "trudniejsze" linijki. Pierwsza (#1) informuje nasz obiekt, że w przypadku skalowania strony nie należy skalować zawartości flash - obiekty mają pozostać tej samej wielkości, zmieni się za to wymiar "płótna" (stage). Kolejna (#5) wywołuje poprzez ExternalInterface funkcję flashSize którą definiujemy w naszym HTML jako funkcję JavaScript, przyjmującą jako argument jeden parametr numeryczny - przekazujemy do niej szerokość obiektu flash.
Mając już gotowy Flash, osadzamy go na stronie nadając np. 100px szerokości - domyślnie, pierwsze wywołanie przekaże do funkcji flashSize() właśnie powyższe 100. Przy przeskalowaniu strony (Ctrl +) przekaże już nową wartość, np. 111px - dzięki temu możemy z proporcji (bądź też bez, jeżeli używamy bazowej szerokości 100px) obliczyć procentowy poziom powiększenia i odpowiednio zareagować (zmienić logikę strony, poinformować odwiedzającego).
Próbowałem wywołanie cykliczne (setInterval) zastąpić reakcją na zdarzenie Event.RESIZE, ale zdaje się, że nie jest one sygnalizowane w takiej konfiguracji stąd też setInterval - na szczęście sama funkcja jest na tyle lekka że nie powoduje praktycznie żadnego dodatkowego obciążenia dla CPU.
Komentarze
Komentarz użytkownika Szymon
13 03 2010hm, jeśli wciskam ctrl+ to wymiary np. diva z tekstem mi się zmieniają ?
u mnie na joggasku, strona wpisów:
document.childNodes[1].childNodes[4].firstElementChild
<div id="the-entry">
document.childNodes[1].childNodes[4].firstElementChild.getBoundingClientRect().width
1210.566650390625
cisnę ctrl+
document.childNodes[1].childNodes[4].firstElementChild.getBoundingClientRect().width
1089.5333251953125
chyba Cie źle zrozumiałem bo o ile procent sie zmieniło to widać bez flesza ?
Komentarz użytkownika Szymon
13 03 2010eee coś się napsuło Oo wtf ?
Komentarz użytkownika Szymon
13 03 2010btw, nie trzeba mierzyć elementów, rozmiar okna (window) tez się zmienia ?
Komentarz użytkownika Szymon
13 03 2010btw, znalazłem u siebie na joggu wpis z obrazkami: http://szymon.jogger.pl/2009/08/26/geek-vs-nerd/
i wyszło mi na to że co prawda szerokość się nie zmienia ale prawo, lewo, góra i dół owszem (i rozmiar okna), tzn. mogę sobie sprawdzić ile procent obrazek zajmuje przed ctrl+ a ile po,tzn.
przed:
width: 108, right: 137, left: 29, obrazek zajmuje: 8%
7 X CTRL+
width: 108, right: 122, left: 14, obrazek zajmuje: 21%
snipet (pewnie zostanie zepsuty przez jakieś czary formatujące):
(function (img) {
['width: ' + String(Math.floor(img.right - img.left)),
'right: ' + Math.floor(img.right),
'left: ' + Math.floor(img.left),
'obrazek zajmuje: ' + String(Math.floor(img.width/window.innerWidth*100)) + '%']
.forEach(function (x) {console.log(x)});
})(document.querySelector('img').getClientRects()[0]);
Komentarz użytkownika BTM
13 03 2010Hm, rzeczywiście - width/height się nie zmienia, ale left/right a i owszem. Dzięki za wskazówkę :)
Komentarz użytkownika Szymon
13 03 2010nie wiem w sumie czy Ci się to do czegoś przyda... btw, jak
ciśniesz Ctrl+ to rozdzielczość okna sie zmniejsza, z takim
skutkiem że to co jest skalowalne jest przeskalowywane, piksmapy
zostają po staremu więc na ekranie są odpowiednio większe (jeśli
rozdzielczość zmniejszysz o 10% to piksmapy będą o 10% większe...
więc nie musisz macać obrazków wystarczy patrzeć jak się
rozdzielczość okna zmienia). Btw, są też opcje skalowania samego
tekstu i też Ci się może coś rozjeżdżać...