Pour un de mes projets (voir BigPictu.re ou bigpicture.js GitHub project ), je dois gérer potentiellement un très, très, très gros <div>
conteneur.
Je savais qu'il y avait un risque de mauvaises performances avec l'approche simple que j'utilise, mais je ne m'attendais pas à ce qu'elle soit principalement présente avec ... Chrome uniquement!
Si vous testez cette petite page (voir code ci-dessous), le panoramique (clic + glisser) sera:
- Normal / lisse sur Firefox
- Normal / lisse même sur Internet Explorer
- Très lent (presque planter) sur Chrome!
Bien sûr, je pourrais ajouter du code (dans mon projet) pour le faire lorsque vous zoomez beaucoup, le texte avec une taille de police potentiellement très grande serait masqué. Mais quand même, pourquoi Firefox et Internet Explorer le gèrent-ils correctement et non Chrome?
Existe-t-il un moyen en JavaScript, HTML ou CSS de dire au navigateur de ne pas essayer de rendre la page entière (qui fait ici 10000 pixels de large) pour chaque action? (ne rendre que la fenêtre courante!)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
html, body {
overflow: hidden;
min-height: 100%; }
#container {
position: absolute;
min-height: 100%;
min-width: 100%; }
.text {
font-family: "Arial";
position: absolute;
}
</style>
</head>
<body>
<div id="container">
<div class="text" style="font-size: 600px; left:100px; top:100px">Small text</div>
<div class="text" style="font-size: 600000px; left:10000px; top:10000px">Very big text</div>
</div>
<script>
var container = document.getElementById('container'), dragging = false, previousmouse;
container.x = 0; container.y = 0;
window.onmousedown = function(e) { dragging = true; previousmouse = {x: e.pageX, y: e.pageY}; }
window.onmouseup = function() { dragging = false; }
window.ondragstart = function(e) { e.preventDefault(); }
window.onmousemove = function(e) {
if (dragging) {
container.x += e.pageX - previousmouse.x; container.y += e.pageY - previousmouse.y;
container.style.left = container.x + 'px'; container.style.top = container.y + 'px';
previousmouse = {x: e.pageX, y: e.pageY};
}
}
</script>
</body>
</html>
Réponses:
Changer pour
position: fixed
semble accélérer les choses.la source
fixed
est évidemment moins complexe à mettre en page et peut-être peuvent-ils faire plus d'optimisations. Mais je n'ai pas regardé le code source du moteur de rendu si vous voulez dire cela ;-)Utilisez à la
transform
place detop/left
:Une démo en direct sur jsFiddle .
la source
fixed
supprime l'élément du flux de texte et économise beaucoup de rendu. Dans la documentation detransform
MDN dit: "... un contexte d'empilement sera créé. Dans ce cas, l'objet agira comme un bloc contenant pour la position: éléments fixes qu'il contient."<div style="position:relative;min-height: 900px;">Your's divs</div>
jsFiddle ainsi faitposition:relative
probablement, ce qui est similaire à la réponse deMais en combinant les réponses Teemu et geert3 - en utilisant la transformation et la position: fixed, Chrome fonctionne beaucoup plus rapidement, même avec de grandes polices.
Tailles de police maximales: http://jsfiddle.net/74w7yL0a/
la source
font-size
et cela pourrait être la raison de l'absence de lenteur sur FF. Mais alors ça aurait dû être très lent sur IE aussi, mais ce n'est pas ... Etrange!En plus de la réponse de Teemu concernant l'utilisation de translate:
Ce que vous devez également utiliser d'autres préfixes de fournisseur, vous pouvez simplement résoudre ce problème en utilisant ceci sur le corps:
et ceci sur html:
cela désactivera cependant le défilement. Donc, ce que je ferais, c'est ajouter un
mousedown
événement au corps et appliquer ces styles en utilisant une classe css chaque fois qu'ilmousedown
est déclenché, et en supprimant cette classemouseup
.la source
style.transform
ou d' utilisertransform
?). Merci au passage pour votre réponse @Prisoner!La réponse de @Teemus fait presque tout.
Utilisez
transform
avectranslate3d
au lieu detop/left
.translate3d
permet l'accélération matérielle.Une démo en direct sur jsFiddle .
la source
J'ai analysé cela et j'ai trouvé que le problème d'origine était lié à l'architecture d'affichage de Chrome et à son utilisation de fils d'arrière-plan pour rendre la page.
Si vous voulez avoir un rendu rapide, allez dans chrome: flags, faites défiler jusqu'au paramètre Peinture côté impl, et définissez "Désactivé", puis redémarrez le navigateur - la souris sera supprimée.
Ce que j'ai trouvé, c'est que si vous activez le compteur FPS, le FPS signalé dans ce scénario est toujours très élevé, même si les performances réelles à l'écran sont très faibles. Mon explication provisoire (n'étant pas un expert en architecture d'affichage Chrome) est que si le thread d'interface utilisateur et l'affichage sont sur des threads séparés, alors il peut y avoir conflit dans le rendu de la div - dans le cas où le thread d'interface utilisateur et le thread de rendu sont sur le même thread, le thread d'interface utilisateur ne peut pas envoyer de messages plus rapidement que le thread d'interface utilisateur ne peut le rendre.
Je suggérerais que cela soit classé comme un bogue Chrome.
la source
Utilisez
display: table
ettable-layout:fixed
sur le div, ou une table enveloppant le div. En HTML:et CSS:
Références
la source