J'attache un écouteur à l'événement orientationchange
:
window.addEventListener('orientationchange', function () {
console.log(window.innerHeight);
});
J'ai besoin d'obtenir la hauteur du document après le orientationchange
. Cependant, l'événement est déclenché avant la fin de la rotation. Par conséquent, la hauteur enregistrée reflète l'état avant le changement d'orientation réel.
Comment enregistrer un événement qui me permettrait de capturer les dimensions des éléments une fois le changement d'orientation terminé?
Le changement d'orientation a besoin d'un délai pour prendre en compte les nouvelles hauteurs et largeurs. Cela fonctionne 80% du temps.
window.setTimeout(function() {
//insert logic with height or width calulations here.
}, 200);
tilisez l'événement resize
L'événement resize inclura la largeur et la hauteur appropriées après un orientationchange, mais vous ne voulez pas écouter tous les événements de redimensionnement. Par conséquent, nous ajoutons un écouteur d'événement de redimensionnement unique après un changement d'orientation:
Javascript :
window.addEventListener('orientationchange', function() {
// After orientationchange, add a one-time resize event
var afterOrientationChange = function() {
// YOUR POST-ORIENTATION CODE HERE
// Remove the resize event listener after it has executed
window.removeEventListener('resize', afterOrientationChange);
};
window.addEventListener('resize', afterOrientationChange);
});
jQuery :
$(window).on('orientationchange', function() {
// After orientationchange, add a one-time resize event
$(window).one('resize', function() {
// YOUR POST-ORIENTATION CODE HERE
});
});
N'utilisez PAS de timeouts
Les délais d'attente ne sont pas fiables - certains appareils ne parviendront pas à capturer leur changement d'orientation dans vos délais d'attente codés en dur; cela peut être pour des raisons imprévues ou parce que l'appareil est lent. Les appareils rapides auront inversement un retard inutile dans le code.
Les solutions de Gajus et burtelli sont robustes mais les frais généraux sont élevés. Voici une version slim assez rapide en 2017, utilisant requestAnimationFrame
:
// Wait until innerheight changes, for max 120 frames
function orientationChanged() {
const timeout = 120;
return new window.Promise(function(resolve) {
const go = (i, height0) => {
window.innerHeight != height0 || i >= timeout ?
resolve() :
window.requestAnimationFrame(() => go(i + 1, height0));
};
go(0, window.innerHeight);
});
}
Utilisez-le comme ceci:
window.addEventListener('orientationchange', function () {
orientationChanged().then(function() {
// Profit
});
});
Il n'y a aucun moyen de capturer la fin de l'événement de changement d'orientation car la gestion du changement d'orientation varie d'un navigateur à l'autre. Tracer un équilibre entre le moyen le plus fiable et le plus rapide pour détecter la fin du changement d'orientation nécessite un intervalle de course et un délai d'attente.
Un écouteur est attaché au orientationchange
. L'appel de l'écouteur démarre un intervalle. L'intervalle suit l'état de window.innerWidth
et window.innerHeight
. L'événement orientationchangeend
est déclenché lorsque noChangeCountToEnd
nombre d'itérations consécutives ne détecte pas de mutation de valeur ou après noEndTimeout
millisecondes, selon la première éventualité.
var noChangeCountToEnd = 100,
noEndTimeout = 1000;
window
.addEventListener('orientationchange', function () {
var interval,
timeout,
end,
lastInnerWidth,
lastInnerHeight,
noChangeCount;
end = function () {
clearInterval(interval);
clearTimeout(timeout);
interval = null;
timeout = null;
// "orientationchangeend"
};
interval = setInterval(function () {
if (global.innerWidth === lastInnerWidth && global.innerHeight === lastInnerHeight) {
noChangeCount++;
if (noChangeCount === noChangeCountToEnd) {
// The interval resolved the issue first.
end();
}
} else {
lastInnerWidth = global.innerWidth;
lastInnerHeight = global.innerHeight;
noChangeCount = 0;
}
});
timeout = setTimeout(function () {
// The timeout happened first.
end();
}, noEndTimeout);
});
Je maintiens une implémentation de orientationchangeend
qui s'étend sur la logique décrite ci-dessus.
J'ai utilisé la solution de contournement proposée par Gajus Kuizunas pendant un certain temps, ce qui était fiable mais un peu lent. Merci quand même, ça a fait le boulot!
Si vous utilisez Cordova ou Phonegap, j'ai trouvé une solution plus rapide - juste au cas où quelqu'un d'autre serait confronté à ce problème à l'avenir. Ce plugin renvoie immédiatement les valeurs de largeur/hauteur correctes: https://github.com/pbakondy/cordova-plugin-screensize
La hauteur et la largeur renvoyées reflètent cependant la résolution réelle, vous devrez donc peut-être utiliser window.devicePixelRatio pour obtenir les pixels de la fenêtre. La barre de titre (batterie, temps, etc.) est également incluse dans la hauteur renvoyée. J'ai utilisé cette fonction de rappel au départ (onDeviceReady)
var successCallback = function(result){
var ratio = window.devicePixelRatio;
settings.titleBar = result.height/ratio-window.innerHeight;
console.log("NEW TITLE BAR HEIGHT: " + settings.titleBar);
};
Dans votre gestionnaire d'événements de changement d'orientation, vous pouvez ensuite utiliser:
height = result.height/ratio - settings.titleBar;
pour obtenir la hauteur intérieure tout de suite. J'espère que cela aide quelqu'un!
J'ai résolu ce problème en combinant quelques-unes des solutions ci-dessus. Le redimensionnement se déclencherait 4 à 5 fois. En utilisant .one, il a tiré trop tôt. Un court délai ajouté à la solution de Christopher Bull a fait l'affaire.
$(window).on('orientationchange', function () {
$(window).one('resize', function () {
setTimeout(reference_to_function, 100);
});
});
J'ai également rencontré le même problème. J'ai donc fini par utiliser:
window.onresize = function(){ getHeight(); }
Il s'agit d'une fonctionnalité expérimentale qui donne la bonne innerHeight et innerWidth une fois l'orientation de l'écran modifiée.
window.screen.orientation.addEventListener('change', function(){
console.log(window.innerHeight)
})
Je pense que l'écoute du redimensionnement de la fenêtre est le moyen le plus sûr de mettre en œuvre une logique de changement d'orientation d'écran.
Il est important de noter que le changement d'orientation n'obtiendra pas la hauteur après le changement, mais plutôt avant. Utilisez redimensionner pour y parvenir.
$(window).bind('orientationchange', function (e) {
var windowHeight = $(window).innerHeight();
console.log('Before Orientation: Height = ' + windowHeight);
$(window).resize(function () {
windowHeight = $(window).innerHeight();
console.log('After Orientation: Height = ' + windowHeight);
});
});
Pour les personnes qui souhaitent simplement le innerHeight
de l'objet fenêtre après le orientationchange
, il existe une solution simple. Utilisation window.innerWidth
. innerWidth
pendant l'événement orientationchange
est le innerHeight
après la fin de orientationchange
:
window.addEventListener('orientationchange', function () {
var innerHeightAfterEvent = window.innerWidth;
console.log(innerHeightAfterEvent);
var innerWidthAfterEvent = window.innerHeight;
console.log(innerWidthAfterEvent);
console.log(screen.orientation.angle);
});
Je ne sais pas si les changements à 180 degrés sont effectués en deux étapes à 90 degrés ou non. Impossible de simuler cela dans le navigateur à l'aide d'outils de développement. Mais si vous souhaitez vous protéger contre une possibilité de rotation complète de 180, 270 ou 360, il devrait être possible d'utiliser screen.orientation.angle
pour calculer l'angle et utiliser la hauteur et la largeur correctes. Le screen.orientation.angle
pendant l'événement est l'angle cible de l'événement orientationchange
.