Czy za pomocą JavaScript można wykryć, kiedy użytkownik zmienia powiększenie strony? Chcę po prostu złapać zdarzenie „zoom” i odpowiedzieć na nie (podobnie do zdarzenia window.onresize).
Dzięki.
Czy za pomocą JavaScript można wykryć, kiedy użytkownik zmienia powiększenie strony? Chcę po prostu złapać zdarzenie „zoom” i odpowiedzieć na nie (podobnie do zdarzenia window.onresize).
Dzięki.
Odpowiedzi:
Nie ma sposobu, aby aktywnie wykryć, czy istnieje powiększenie. Znalazłem tutaj dobry wpis o tym, jak możesz spróbować go wdrożyć.
Znalazłem dwa sposoby wykrywania poziomu powiększenia. Jeden ze sposobów wykrywania zmian poziomu powiększenia polega na tym, że wartości procentowe nie są powiększane. Wartość procentowa odnosi się do szerokości rzutni, a zatem nie ma wpływu na powiększenie strony. Jeśli wstawisz dwa elementy, jeden z pozycją w procentach, a drugi z tą samą pozycją w pikselach, będą się one rozsuwały po powiększeniu strony. Znajdź stosunek między pozycjami obu elementów i masz poziom powiększenia. Zobacz przypadek testowy. http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
Możesz to również zrobić za pomocą narzędzi z powyższego postu. Problem polega na tym, że w mniejszym lub większym stopniu dokonujesz przemyślanych przypuszczeń, czy strona została powiększona. W niektórych przeglądarkach będzie to działać lepiej niż w innych.
Nie ma sposobu, aby stwierdzić, czy strona jest powiększona, jeśli wczytują ją podczas powiększania.
document.body.offsetWidth
Używam tego fragmentu JavaScript do reagowania na „zdarzenia” Zoom.
Sonduje szerokość okna. (Jak sugerowano na tej stronie (do której odsyłał Ian Elliott): http://novemberborn.net/javascript/page-zoom-ff3 [archiwum] )
Testowane w Chrome, Firefox 3.6 i Opera, a nie w IE.
Pozdrawiam Magnus
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);
})();
Dobre wieści wszyscyniektórzy ludzie! Nowsze przeglądarki wyzwalają zdarzenie zmiany rozmiaru okna po zmianie powiększenia.
Określmy px_ratio jak poniżej:
współczynnik px = stosunek pikseli fizycznych do pikseli css.
jeśli któryś z powiększa Strona, piksele widoku (piksele różnią się od pikseli) zmniejszają się i powinny być dopasowane do ekranu, więc współczynnik (piksel fizyczny / CSS_px) musi się zwiększyć.
ale przy zmianie rozmiaru okna rozmiar ekranu zmniejsza się, podobnie jak piksele. więc stosunek się utrzyma.
ale
resizing: wyzwalanie zdarzenia windows.resize -> nie zmienia 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;
}
}
Kluczową kwestią jest różnica między CSS PX a Physical Pixel.
https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e
To działa dla mnie:
var deviceXDPI = screen.deviceXDPI;
setInterval(function(){
if(screen.deviceXDPI != deviceXDPI){
deviceXDPI = screen.deviceXDPI;
... there was a resize ...
}
}, 500);
Jest potrzebny tylko w IE8. Wszystkie inne przeglądarki w naturalny sposób generują zdarzenie zmiany rozmiaru.
Istnieje sprytna wtyczka, yonran
która umożliwia wykrywanie. Oto jego wcześniej udzielone pytanie w StackOverflow. Działa w większości przeglądarek. Aplikacja jest tak prosta:
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
przycisk w opcji Dostępność. Demo nie zareaguje na zmianę.
Chciałbym zasugerować ulepszenie do poprzedniego rozwiązania ze śledzeniem zmian szerokości okna. Zamiast utrzymywać własną tablicę detektorów zdarzeń, możesz użyć istniejącego systemu zdarzeń javascript i wyzwolić własne zdarzenie po zmianie szerokości i powiązać z nim procedury obsługi zdarzeń.
$(window).bind('myZoomEvent', function() { ... });
function pollZoomFireEvent()
{
if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}
Ograniczenie / odrzucenie może pomóc w zmniejszeniu wskaźnika wywołań twojego handlera.
Możesz również uzyskać zdarzenia zmiany rozmiaru tekstu i współczynnik powiększenia, wstawiając element div zawierający co najmniej nierozerwalną spację (prawdopodobnie ukrytą) i regularnie sprawdzając jego wysokość. Jeśli zmienia się wysokość, zmienił się rozmiar tekstu (i wiesz ile - to również uruchamia się, nawiasem mówiąc, jeśli okno zostanie powiększone w trybie pełnej strony, a nadal uzyskasz prawidłowy współczynnik powiększenia, o tej samej wysokości / stosunek wysokości).
<script>
var zoomv = function() {
if(topRightqs.style.width=='200px){
alert ("zoom");
}
};
zoomv();
</script>
W iOS 10 można dodać detektor zdarzenia do touchmove
zdarzenia i wykryć, czy strona jest powiększona o aktualne zdarzenie.
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;
});
Chociaż jest to pytanie sprzed 9 lat, problem nadal występuje!
Wykrywałem zmianę rozmiaru, jednocześnie wykluczając powiększenie projektu, więc zmodyfikowałem kod, aby działał tak, aby wykrywał zarówno zmianę rozmiaru, jak i powiększenie, wykluczające się wzajemnie. Działa przez większość czasu, więc jeśli większość jest wystarczająco dobra dla twojego projektu, to powinno być pomocne! Wykrywa powiększanie w 100% w tym, co do tej pory testowałem. Jedynym problemem jest to, że jeśli użytkownik wpadnie w szał (np. Spastycznie zmienia rozmiar okna) lub okno się opóźnia, może uruchomić się jako powiększenie zamiast zmiany rozmiaru okna.
Działa poprzez wykrywanie zmiany window.outerWidth
lub window.outerHeight
zmiany rozmiaru okna podczas wykrywania zmiany window.innerWidth
lub window.innerHeight
niezależności od zmiany rozmiaru okna jako powiększenia.
//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);
Uwaga: moje rozwiązanie jest podobne do rozwiązania KajMagnus, ale to działa lepiej dla mnie.
0.05
bez podania przynajmniej dobrego wyjaśnienia. ;-) Na przykład wiem, że w Chrome, konkretnie, 10% to najmniejsza wartość, jaką przeglądarka powiększy w każdym przypadku, ale nie jest jasne, czy dotyczy to innych przeglądarek. fyi, zawsze upewnij się, że Twój kod jest przetestowany i bądź przygotowany na jego obronę lub ulepszenie.
Oto czyste rozwiązanie:
// 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);
});
Zdarzenie resize działa w nowoczesnych przeglądarkach, dołączając zdarzenie do window
, a następnie odczytując wartości body
elementu lub innego elementu, na przykład ( .getBoundingClientRect () ).
W niektórych wcześniejszych przeglądarkach można było zarejestrować programy obsługi zdarzeń zmiany rozmiaru na dowolnym elemencie HTML. Nadal można ustawić atrybuty onresize lub użyć metody addEventListener (), aby ustawić procedurę obsługi dla dowolnego elementu. Jednak zdarzenia zmiany rozmiaru są uruchamiane tylko w obiekcie okna (tj. Zwracane przez document.defaultView). Tylko programy obsługi zarejestrowane w obiekcie okna będą otrzymywać zdarzenia zmiany rozmiaru .
window.addEventListener("resize", getSizes, false)
function getSizes(){
let body = document.body
console.log(body.clientWidth +"px x "+ body.clientHeight + "px")
}
Inna alternatywa : ResizeObserver API
W zależności od układu możesz obserwować zmianę rozmiaru określonego elementu.
Działa to dobrze w układach „responsywnych”, ponieważ rozmiar kontenera zmienia się podczas powiększania.
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>
Uważaj, aby nie przeciążać zadań javascript związanych ze zdarzeniami dotyczącymi gestów użytkownika. Użyj requestAnimationFrame, gdy potrzebujesz przerysowań.
Według MDN „matchMedia” to właściwy sposób na zrobienie tego https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes
jest to trochę skomplikowane, ponieważ każda instancja może oglądać tylko jeden MQ naraz, więc jeśli jesteś zainteresowany jakimkolwiek zmianą poziomu powiększenia, musisz wykonać kilka dopasowań ... ale ponieważ przeglądarka jest odpowiedzialna za emitowanie zdarzeń, prawdopodobnie wciąż bardziej wydajne niż odpytywanie, i możesz zdławić lub odrzucić wywołanie zwrotne lub przypiąć je do ramki animacji lub czegoś podobnego - oto implementacja, która wydaje się dość zgryźliwa, możesz zamienić _throttle lub cokolwiek innego, jeśli już na tym polegasz.
Uruchom fragment kodu i powiększaj i pomniejszaj w przeglądarce, zanotuj zaktualizowaną wartość w znacznikach - testowałem to tylko w przeglądarce Firefox! daj mi znać, jeśli zauważysz jakieś problemy.
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>
Odpowiadam na link sprzed 3 lat, ale wydaje mi się, że jest to bardziej akceptowalna odpowiedź,
Utwórz plik .css jako,
@media screen and (max-width: 1000px)
{
// things you want to trigger when the screen is zoomed
}
NA PRZYKŁAD:-
@media screen and (max-width: 1000px)
{
.classname
{
font-size:10px;
}
}
Powyższy kod sprawia, że rozmiar czcionki wynosi „10px” przy powiększeniu ekranu do około 125%. Możesz sprawdzić inny poziom powiększenia, zmieniając wartość „1000px”.
max-width
współczynnikiem powiększenia a współczynnikiem powiększenia?