web-dev-qa-db-fra.com

Comment puis-je surveiller la position du défilement lors du défilement dans Safari sur iOS?

J'utilise actuellement $(window).bind('scroll', foo); pour surveiller $(window).scrollTop() et faire des trucs pour créer un effet de parallaxe.

Dans tous les navigateurs de bureau foo() est appelé pour chaque pixel que l'utilisateur fait défiler, et tout est Nice et dandy. Dans Safari sur iOS, l'événement de défilement n'est déclenché qu'après la fin du défilement.

J'ai ajouté $(window).bind('touchmove', foo); pour m'assurer que la fonction est appelée pendant le balayage dans iOS, et cela m'a permis d'aller un peu plus loin. Lorsque l'utilisateur relâche le doigt, la page continue de défiler, mais l'événement cesse de se déclencher.

Des idées?

26
tkalve

Je recommande fortement d'utiliser la bibliothèque javascript "Skrollr". C'est de loin la meilleure option d'animation de défilement mobile que j'ai trouvée à ce jour et est très facile à mettre en œuvre rapidement. Créez des animations et manipulez CSS en fonction d'une position de défilement de début et de fin. Créez autant de positions de défilement de données et d'animations que vous le souhaitez pour la plupart des propriétés CSS standard.

Dans l'exemple suivant, la couleur d'arrière-plan s'anime au cours d'un défilement de 500 pixels:

<div data-0="background-color:rgb(0,0,255);" data-500="background-color:rgb(255,0,0);">WOOOT</div>

Récupérez le référentiel sur Git: https://github.com/Prinzhorn/skrollr

Exemple de démonstration de Skrollr: http://prinzhorn.github.io/skrollr/

Exemple génial du monde réel: http://www.fontwalk.de/03/

4
negrelja

Quand j'ai vu votre question, je comptais faire un polyfill pour cela (si cela n'existe pas?). Malheureusement, j'ai eu très peu de temps.

L'idée est d'avoir un setInterval, qui est initié ontouchstart, et il vérifie si document.body.scrollTop a changé depuis la dernière fois, par exemple. pour toutes les 20 millisecondes. Et si c'est le cas, nous envoyons manuellement l'événement de défilement. Sinon, nous clearInterval car apparemment il n'y a plus de défilement.

Ce serait en bref. Si vous avez plus de temps (que moi), n'hésitez pas à essayer ces directives.

Edit: Maintenant, en lisant plus loin, la même idée semble être suggérée sur l'autre réponse. Êtes-vous certain que les intervalles sont arrêtés lors du défilement sur iPad?

4
zvona

La page Web d'Apple pour iPhone 5c utilise des effets de défilement de parallaxe qui semblent continuer avec votre doigt toujours en contact avec l'écran et le défilement. Je suppose donc que javascript ne peut pas être entièrement désactivé pendant le défilement. Tumult Hype offre également cette fonctionnalité.

2
Gaz

Bien que cela ne soit pas possible hors de la boîte, pour ainsi dire, vous pouvez le faire en utilisant iscroll

Donc, vous utiliseriez iScroll pour iOS et Android appareils mobiles/tablettes, et utiliseriez la façon dont vous le faites actuellement pour les appareils de bureau.

iScroll a un tas d'options pour les fonctions de rappel à appeler sur certains événements - tels que 'onScrollMove', 'onBeforeScrollEnd', 'onTouchEnd', etc. Malheureusement, il n'y a pas d'option pour exécuter un rappel sur "CHAQUE changement de position, y compris les changements causée par l'élan du défilement après que l'utilisateur a cessé de toucher l'écran ". Mais, il est assez facile d'en ajouter un.

Dans la source iScroll, autour de la ligne 127, près du commentaire "// Events", ajoutez une nouvelle variable:

onPosChange: null

Ensuite, autour de la ligne 308, à la fin de la fonction "_pos", ajoutez cette ligne:

if (this.options.onPosChange) this.options.onPosChange.call();

(qui appellera simplement la fonction passée dans l'option "onPosChange", si elle existe).

Cela fait, l'exemple de code suivant configurera iScroll pour le div avec id = "iscroll_container" et imprimera le décalage Y sur la console chaque fois qu'il change:

var myScroll;
function loaded() {
    myScroll = new iScroll('iscroll_container', { onPosChange: actOnScroll });
}

document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);

//Use this for high compatibility (iDevice + Android)
document.addEventListener('DOMContentLoaded', function () { setTimeout(loaded, 200); }, false);

function actOnScroll(){
    console.log('got a scroll move! Vert offset is: ' + myScroll.y);
}

Remarque, Ben the Bodyguard Parallax Site fonctionne sur iPad en utilisant iScroll (ils utilisent une version beaucoup plus ancienne d'iscroll et ne le font pas exactement comme je l'ai décrit ici)

En outre, Life of Pi Parallax Site fonctionne très bien sur iPad - je ne peux pas comprendre comment ils le font, mais au moins cela prouve que c'est possible!

1
joshua.paling

Comme je sais, il n'y a pas d'exécution javascript lors du défilement sur la plupart des appareils mobiles. Il existe des solutions de contournement (par exemple iscroll). Iscroll utilise la technique de transformation "css". Mais il n'y a aucun moyen d'exécuter javascript pendant le défilement. Je suppose que l'algorithme de défilement lisse est trop cher.

0
Andreas Dyballa

Cela pourrait être un bogue avec jQuery lui-même: http://bugs.jquery.com/ticket/6446

Ce ticket est ouvert depuis un certain temps et concerne iOS 4, mais vous devriez peut-être étudier le calcul de la position de défilement avec du javascript pur.

0
Jason Barry