Cet article présente une méthode de conception de site Web à la mode et comment créer un site hautes performances via HTML5 et les mécanismes de rendu du navigateur, du plus superficiel au plus profond.
Cet article implique de nombreux principes de refonte du navigateur et d'optimisation des performances. Il s'agit également d'une extension et d'une continuation de "Pratique d'optimisation des performances de défilement Web". Le niveau de difficulté est intermédiaire et avancé. .
Introduction
Les sites Parallax font fureur ces derniers temps, il suffit de consulter ces sites :
Le vieux Pulteney rame jusqu'au poteau
Adidas Snowboarding
BBC News - James Bond : Voitures, slogans et bisous
Si vous ne les connaissez pas encore, ce sont en réalité des sites où la structure visuelle de la page change au fur et à mesure du défilement. Dans des circonstances normales, les éléments de la page sont mis à l'échelle, pivotés ou déplacés vers la position de défilement.
Page de démonstration de notre effet parallaxe
C'est une chose que vous aimiez les sites Web parallaxe, mais ce que nous pouvons confirmer, c'est qu'il s'agit définitivement d'un trou noir de performance . La raison en est que lorsque vous faites défiler, le navigateur essaiera d'effectuer des optimisations de performances sur l'endroit où le nouveau contenu apparaît (en fonction de la direction de défilement), et en général, moins le navigateur est visuellement mis à jour, mieux c'est. Ceci est rare pour les sites Web parallaxe, car les grands éléments visuels changeront plusieurs fois tout au long de la page, obligeant le navigateur à redessiner la page entière (pourquoi c'est un trou noir de performances, vous pouvez vous référer à mon article "Pratique d'optimisation des performances de défilement Web ").
Il est raisonnable de résumer les sites Web de parallaxe comme suit :
1. Lorsque vous faites défiler la page vers le haut ou vers le bas, l'élément d'arrière-plan change de position, pivote ou évolue.
2. Le contenu de la page, tel que le texte ou les petites images, défile d'une manière spéciale de haut en bas.
Nous avons déjà présenté les performances de défilement et la manière dont vous pouvez les optimiser pour améliorer la réactivité de votre application. Cet article s’appuiera sur cela, vous devez donc d’abord lire l’article ci-dessus.
La question est donc maintenant la suivante : si vous créez un site Web à défilement parallaxe, devez-vous effectuer des repeintures coûteuses, ou existe-t-il d'autres méthodes que vous pouvez adopter pour maximiser les performances ? Jetons un coup d'œil aux options.
Méthode 1 : Utilisation d'éléments DOM et positionnement absolu
C'est probablement la façon dont la plupart des gens choisissent. Il existe de nombreux éléments sur la page et lorsque des événements de défilement sont déclenchés, de nombreuses mises à jour visuelles se produiront sur ces éléments. Ici, je montre une page de démonstration.
Si vous activez le mode cadre dans la chronologie des outils de développement et faites défiler vers le haut ou vers le bas, vous remarquerez des opérations de dessin plein écran coûteuses. Si vous faites défiler plusieurs fois, vous pouvez voir plusieurs événements de défilement dans une seule image, chacun déclenchant le travail de mise en page.
Les outils de développement affichent un grand nombre d'opérations de dessin et plusieurs mises en page déclenchées par des événements dans un cadre
Il est important de se rappeler que pour réaliser À 60 ips (correspondant à un taux de rafraîchissement typique d’un moniteur de 60 Hz), nous devons tout faire en près de 16 ms. Dans cette première version, chaque fois que nous obtenons un événement de défilement, nous devons effectuer une mise à jour visuelle, mais comme nous l'avons discuté dans les articles précédents - "Utilisation de requestAnimationFrame pour implémenter des animations plus simples" et "Pratique d'optimisation des performances de défilement Web". Ceci est incompatible avec le rythme de mise à jour du navigateur. Soit nous manquons d’images, soit nous effectuons trop de travail dans une seule image. Cela peut facilement donner à votre site un aspect inconfortable et contre nature, entraînant la frustration des utilisateurs.
Déplaçons le code de mise à jour visuelle de l'événement scroll vers le rappel requestAnimationFrame, et récupérons simplement la valeur de défilement dans le rappel de l'événement scroll. Nous démontrons ce changement dans notre deuxième démo.
Si vous répétez le test de roulement, vous remarquerez peut-être une légère amélioration, mais pas beaucoup. La raison en est que les opérations de mise en page déclenchées par le défilement sont coûteuses et que nous n'effectuons désormais les opérations de mise en page qu'une fois par image.
Les outils de développement affichent un grand nombre d'opérations de dessin et plusieurs mises en page déclenchées par des événements dans une seule image
Nous pouvons désormais le traiter dans chaque image. Une ou des centaines d'événements de défilement, mais plus important encore, nous stockons uniquement la valeur de défilement la plus récente à utiliser lorsque le rappel requestAnimationFrame est déclenché et effectuons des mises à jour visuelles. La clé est que nous sommes passés de l'optimisation des mises à jour visuelles à chaque fois que nous recevons un événement de défilement à le faire au bon moment qui nous est proposé par le navigateur. Pensez-vous que c'est assez puissant ?
Le principal problème de cette méthode est que que nous utilisions requestAnimationFrame ou non, nous générerons essentiellement une couche de la page entière, ce qui nécessite un travail important et coûteux lors du déplacement de ces visuels. éléments Redessiner . Habituellement, le redessinage est une opération de blocage (bien que cela soit optimisé), ce qui signifie que le navigateur ne peut pas effectuer d'autres travaux en même temps, et nous pouvons souvent dépasser la limite de temps de traitement d'image de 16 ms du navigateur, ce qui signifie qu'il y aura des retards de performances. Situation de Dayton.
Méthode 2 : Utilisation d'éléments DOM et transformation 3D
En plus du positionnement absolu, une autre méthode que nous pouvons utiliser est la transformation 3D (transformation). Dans ce cas, nous pouvons voir que chaque élément traité avec 3D Transform aboutit à un nouveau calque. En revanche, dans la méthode 1, nous devons redessiner une grande partie de la page si quelque chose change.
Cela signifie que les choses sont très différentes avec cette méthode : nous pouvons avoir un calque pour tout élément auquel une transformation 3D est appliquée. Si nous faisons cela en transformant plus d'éléments, nous n'avons pas besoin de redessiner de calques et le GPU est capable de gérer le déplacement des éléments et la composition de la page entière. Vous vous demandez peut-être pourquoi la transformation 3D est utilisée à la place de la 3D, la raison est que la transformation 2D ne garantit pas l'obtention d'un nouveau calque, tandis que la 3D la transformation fait .
Ceci est une autre démo utilisant la transformation 3D. Au fur et à mesure que vous faites défiler, vous pouvez constater que les performances se sont beaucoup améliorées.
Plusieurs fois, les gens utilisent la technique -webkit-transform:translateZ(0) et peuvent constater de merveilleuses améliorations de performances (Yujie Remarque : à propos de cette méthode, elle utilise en fait la conversion 3D pour activer le matériel du navigateur. L'accélération est une sorte de hack rarement mentionnée dans les informations nationales, mais il existe de nombreux articles sur l'optimisation des performances de développement d'applications mobiles en Chine et sur « Amélioration des performances des pages Web HTML5 » dans les pays étrangers « Augmentation des performances du HTML et du JavaScript sur les appareils mobiles ». . Cette méthode peut fonctionner normalement maintenant, mais elle entraînera quelques problèmes :
1. Elle n'est pas compatible avec le navigateur
2. Elle oblige le navigateur à créer un nouveau calque. Un grand nombre de couches peuvent créer d’autres goulots d’étranglement en matière de performances, elles doivent donc être utilisées avec parcimonie.
3. Il est désactivé sur certaines versions Webkit des ports.
Vous devez donc être très prudent si vous adoptez cette méthode, c'est une solution temporaire au problème. Dans un monde parfait, nous n'y penserions même pas, et avec les navigateurs qui s'améliorent chaque jour, qui sait, peut-être qu'un jour nous n'en aurons plus besoin.
Méthode 3 : utiliser un canevas à position fixe ou WebGL
La dernière méthode que nous devons considérer est d'utiliser un canevas à position fixe sur la page et de mettre l'image transformée est tracé ci-dessus. À première vue, ce n'est peut-être pas la solution la plus efficace, mais elle présente plusieurs avantages :
On n'a plus besoin de beaucoup de travail de compositing, Parce que la page n'a qu'un seul élément - Canvas ;
Nous pouvons traiter efficacement un seul bitmap grâce à l'accélération matérielle
L'API Canvas2D est parfaite ; pour nous Le type de transformations à effectuer, ce qui signifie que le développement et la maintenance sont plus gérables.
L'utilisation de l'élément Canvas nous donne un nouveau calque, mais il n'a qu'un seul calque, alors que dans la méthode 2, nous créons un nouveau calque pour chaque élément auquel la transformation 3D est appliquée, il y a donc un travail supplémentaire à faire. Ces calques sont composés ensemble.
Si vous regardez la démonstration de cette méthode et l'observez dans les outils de développement, vous constaterez que ses performances sont encore meilleures. Dans cette méthode, il suffit d'appeler l'API drawImage sur Canvas, de définir l'image d'arrière-plan et chaque bloc de couleur à dessiner à la bonne position sur l'écran.
/** * Updates and draws in the underlying visual elements to the canvas. */ function updateElements () { var relativeY = lastScrollY / h; // Fill the canvas up context.fillStyle = "#1e2124"; context.fillRect(0, 0, canvas.width, canvas.height); // Draw the background context.drawImage(bg, 0, pos(0, -3600, relativeY, 0)); // Draw each of the blobs in turn context.drawImage(blob1, 484, pos(254, -4400, relativeY, 0)); context.drawImage(blob2, 84, pos(954, -5400, relativeY, 0)); context.drawImage(blob3, 584, pos(1054, -3900, relativeY, 0)); context.drawImage(blob4, 44, pos(1400, -6900, relativeY, 0)); context.drawImage(blob5, -40, pos(1730, -5900, relativeY, 0)); context.drawImage(blob6, 325, pos(2860, -7900, relativeY, 0)); context.drawImage(blob7, 725, pos(2550, -4900, relativeY, 0)); context.drawImage(blob8, 570, pos(2300, -3700, relativeY, 0)); context.drawImage(blob9, 640, pos(3700, -9000, relativeY, 0)); // Allow another rAF call to be scheduled ticking = false; } /** * Calculates a relative disposition given the page’s scroll * range normalized from 0 to 1 * @param {number} base The starting value. * @param {number} range The amount of pixels it can move. * @param {number} relY The normalized scroll value. * @param {number} offset A base normalized value from which to start the scroll behavior. * @returns {number} The updated position value. */ function pos(base, range, relY, offset) { return base + limit(0, 1, relY - offset) * range; } /** * Clamps a number to a range. * @param {number} min The minimum value. * @param {number} max The maximum value. * @param {number} value The value to limit. * @returns {number} The clamped value. */ function limit(min, max, value) { return Math.max(min, Math.min(max, value)); }
Cette approche est vraiment utile pour traiter des images de grande taille (ou d'autres éléments faciles à écrire sur un Canvas) ou De gros blocs de texte peuvent certainement être difficiles. Mais sur votre site internet, cela peut s’avérer être la solution la plus adaptée. Si vous devez traiter du texte sur Canvas, vous souhaiterez peut-être utiliser l'API fillText, mais elle a un coût d'accès (vous venez de convertir le texte en bitmap !) et vous devez gérer l'habillage du texte et d'autres problèmes. Vous devez essayer d'éviter de faire cela.
Après avoir tant discuté, nous n'avons aucune raison de supposer que l'élément Canvas doit être utilisé pour travailler avec la parallaxe. Nous pouvons utiliser WebGL si le navigateur le prend en charge. La clé ici est que WebGL est le moyen le plus direct entre toutes les API et la carte graphique, et lorsque les effets de votre site sont complexes, les performances sont plus susceptibles d'atteindre 60 ips.
Votre réaction la plus immédiate sera peut-être que l'utilisation de WebGL est excessive ou qu'elle n'est pas largement prise en charge, mais si vous utilisez une bibliothèque similaire à Three.js, vous pouvez toujours recourir à l'élément Canvas. en même temps, votre code peut être extrait de manière cohérente et conviviale. Il suffit d'utiliser Modernizr pour détecter le support de l'API correspondante :
// check for WebGL support, otherwise switch to canvas if (Modernizr.webgl) { renderer = new THREE.WebGLRenderer(); } else if (Modernizr.canvas) { renderer = new THREE.CanvasRenderer(); }
Utilisez ensuite le Three.js API, et au lieu de gérer le contexte vous-même. Voici une démo qui prend en charge les deux méthodes de rendu.
Le dernier problème de cette approche est que si vous n'aimez pas particulièrement ajouter des éléments supplémentaires à la page, vous pouvez toujours utiliser le canevas comme élément d'arrière-plan dans les navigateurs Firefox et Webkit. Évidemment, cela n’est pas universellement applicable, vous devez donc être prudent à ce sujet.
Dégradation progressive
La principale raison pour laquelle les développeurs utilisent par défaut des éléments positionnés de manière absolue au lieu d'autres méthodes peut simplement être une question de prise en charge du navigateur. Cette approche est erronée dans une certaine mesure, car pour les navigateurs plus anciens, elle ne peut fournir qu'une très mauvaise expérience de rendu. Même dans les navigateurs modernes, l’utilisation du positionnement absolu ne conduit pas nécessairement à de bonnes performances.
Une meilleure solution consiste à éviter d'essayer des effets de parallaxe sur des navigateurs plus anciens et à utiliser uniquement les meilleurs navigateurs pour garantir que la bonne API peut être utilisée pour restituer l'effet de site. Bien sûr, si vous utilisez Three.js, vous devriez pouvoir basculer facilement entre les moteurs de rendu en fonction du support dont vous avez besoin.
Conclusion
Nous avons évalué plusieurs façons de gérer les zones fortement redessinées, depuis les éléments positionnés de manière absolue jusqu'à l'utilisation de canevas à position fixe. Bien sûr, la manière dont vous mettrez en œuvre cela dépendra de ce que vous essayez d’atteindre et de votre conception spécifique, mais il est bon de savoir qu’il existe des options. Dans l’exemple de cet article, nous avons réussi à optimiser d’un effet relativement lent, inférieur à 30 ips, à un effet fluide de 60 ips.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!