English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Dans certains sites qui supportent l'écriture d'articles en markdown, les pages de création de contenu en arrière-plan, généralement, elles supportent la prévisualisation instantanée de markdown, c'est-à-dire que la page entière est divisée en deux parties, la moitié gauche est le texte markdown que vous entrez, et la moitié droite est le prévisualisation instantanée de la page correspondante, par exemple, ci-dessous est l'effet de prévisualisation instantanée markdown de la page de création de contenu en arrière-plan de CSDN :
Cet article ne décrit pas comment réaliser cet effet à partir de zéro (suite Il est probable Je vais isoler l'article,), mis à part cela, regardons les deux éléments de conteneur principaux de la page, à savoir l'élément de boîte de saisie markdown et l'élément de visualisation de prévisualisation
L'objet de cet article est de discuter de la manière dont, lorsque le contenu de ces deux éléments de conteneur dépasse la hauteur du conteneur, c'est-à-dire que les deux apparaissent des cadres de défilement, comment faire en sorte que l'un des éléments de conteneur défile lorsque l'autre l'element suit également.
Structure DOM
Puisque cela concerne la barre de défilement, la première chose qui vient à l'esprit est une propriété de contrôle de la hauteur de la barre de défilement en JavaScript : scrollTop. Si l'on peut contrôler cette valeur, on peut naturellement contrôler le défilement de la barre de défilement.
Pour la structure DOM suivante :
<div id="container"> <div class="left"></div> <div class="right"></div> </div>
Dans ce cas, l'élément .left est l'élément de conteneur de la moitié gauche de l'entrée, l'élément .right est l'élément de conteneur de la moitié droite de l'affichage, et .container est le parent commun de ces deux éléments.
Comme il est nécessaire de définir le défilement de débordement, il est nécessaire de définir les styles correspondants (seulement les styles clés, pas tous) :
#container { display: flex; border: 1px solid #bbb; } .left, .right { flex: 1; height: 100%; word-wrap: break-word; overflow-y: scroll; }
Ensuite, insérez suffisamment de contenu dans les éléments .left et .right pour qu'ils apparaissent avec une barre de défilement, c'est ce genre d'effet :
Le style est sorti d'une manière générale, donc on peut maintenant effectuer une série d'opérations sur ces DOM.
Première tentative
La idée générale est de surveiller les événements de défilement de deux éléments de conteneur, et lorsque l'un des éléments défile, obtenir la valeur de l'attribut scrollTop de cet élément, puis mettre cette valeur à la valeur scrollTop de l'autre élément de défilement.
Par exemple :
var l=document.querySelector('.left') var r=document.querySelector('.right') l.addEventListener('scroll',function(){ r.scrollTop = l.scrollTop )
L'effet est le suivant :
Il semble très bien, mais maintenant, non seulement je veux que le côté droit suive le défilement du côté gauche, mais aussi que le côté gauche suive le défilement du côté droit, donc ajoutez le code suivant :
addEventListener('scroll',function(){ r.scrollTop = l.scrollTop )
Il semble très bien, mais, il n'est pas aussi simple que cela.
Lorsque vous utilisez la molette de la souris pour faire défiler à ce moment-là, vous vous rendez compte que le défilement est un peu difficile, comme si les deux éléments de conteneur de défilement étaient bloqués par quelque chose, et il est difficile de défilement.
Une analyse détaillée montre que la cause est simple : lorsque vous faites défiler à gauche, l'événement de défilement de gauche est déclenché, et donc le côté droit suit le défilement. Mais en même temps, le défilement du côté droit suit également, et donc l'événement de défilement du côté droit est déclenché à nouveau, et donc le côté gauche doit également suivre le défilement du côté droit... et ainsi de suite, on entre dans une situation similaire à une déclenchement réciproque, c'est pourquoi on trouve que le défilement est difficile.
Résoudre le problème de déclenchement simultané de l'événement de défilement
Pour résoudre les problèmes mentionnés ci-dessus, il existe temporairement deux solutions.
Remplacez l'événement scroll par l'événement mousewheel
Puisque l'événement scroll peut être déclenché non seulement par le défilement actif de la souris, mais aussi par le changement de scrollTop de l'élément conteneur, le défilement actif de l'élément est en réalité déclenché par la molette de la souris, donc on peut remplacer l'événement scroll par un événement sensible à la molette de la souris plutôt qu'à la défilement de l'élément : 'mousewheel', et le code d'écoute mentionné précédemment devient :
addEventListener('mousewheel',function(){ r.scrollTop = l.scrollTop ) r.addEventListener('mousewheel',function(){ l.scrollTop = r.scrollTop )
L'effet est le suivant :
Il semble qu'il y ait un certain usage, mais en réalité, il y a encore deux problèmes.
Lorsque vous faites défiler un élément conteneur, l'autre élément conteneur suit, mais il ne défile pas en douceur, et il y a un rebond instantané évident en hauteur
Après une recherche en ligne, je n'ai pas trouvé de contenu sur la fréquence de roulement de l'événement wheel, je suppose que c'est une fonctionnalité de cet événement.
Chaque fois que la souris roule, elle n'est pas vraiment 1px en unité, son unité minimale est beaucoup plus petite que celle de l'événement scroll, j'ai utilisé ma souris pour dérouler dans le navigateur chrome, chaque fois que je déroule, la distance parcourue est toujours 100px, différentes souris ou navigateurs devraient avoir cette valeur, et l'événement wheel écoute vraiment l'événement où la molette de la souris passe par un point de fixation de la dent, ce qui explique pourquoi il y a un phénomène de rebond.
En règle générale, chaque fois que la molette de la souris passe par un point de fixation de la dent, on peut détecter un événement wheel, de début à fin, l'élément qui a été déplacé par la souris a déjà défilé 100px, donc l'autre élément conteneur qui suit le défilement a bougé instantanément 100px
Et c'est pourquoi l'événement scroll mentionné précédemment ne fait pas apparaître un rebond instantané chez les éléments de défilement suivants, c'est parce que chaque fois que scrollTop change pour les éléments de défilement suivants, sa valeur ne changera pas 100px une si grande portée, il est probable qu'il ne soit pas aussi petit 1px, mais en raison de sa fréquence de déclenchement élevée et de la petite portée de défilement, au moins visuellement, cela est un défilement en douceur.
Wheel n'est qu'un écouteur d'événement de roue de souris, mais si vous glissez la barre de défilement à l'aide de la souris, cet événement ne sera pas déclenché, et les autres éléments conteneurs ne suivront pas le défilement.
En réalité, c'est très facile à résoudre, en utilisant le glisser-déposer de la souris pour déplacer la barre de défilement est certainement capable de déclencher l'événement scroll, et dans ce cas, vous pouvez facilement déterminer à quel élément conteneur appartient cette barre de défilement qui est glissée, il suffit de traiter l'événement de défilement de ce conteneur, et de ne pas traiter l'événement de défilement du conteneur suivant.
les problèmes de compatibilité de l'événement wheel
l'événement wheel est DOM Level3 d'événements standard, mais en plus de cet événement, il y a beaucoup d'événements non standard, différents navigateurs utilisent des normes différentes, donc il peut être nécessaire de prendre en compte la compatibilité selon le cas, voir MDN MouseWheelEvent pour plus de détails
Si vous ne supportez pas les rebonds de wheel et les différents compatibilités, il existe en fait une autre voie à suivre, toujours l'événement scroll, mais il faut faire un peu plus de travail supplémentaire.
Le problème de l'événement scroll est qu'il n'y a pas de jugement de quel conteneur de défilement est actif en ce moment, mais une fois que le conteneur de défilement actif est déterminé, cela est facile à gérer, par exemple, dans l'exemple mentionné précédemment avec l'événement wheel, la raison pour laquelle on peut utiliser l'événement scroll est qu'il est facile de déterminer quel est le conteneur de défilement actif.
Donc, le problème clé est de déterminer quel est le conteneur de défilement actif en ce moment, une fois que ce problème est résolu, tout reste facile à gérer.
Que ce soit le défilement de la molette de la souris ou le déplacement de la barre de défilement en glissant la souris, cela déclenche l'événement scroll, et à ce moment-là, les coordonnées de la souris sont certainement à l'intérieur de l'aire occupée par l'élément de conteneur de défilement sur l'axe Z, c'est-à-dire que sur l'axe Z, la souris est flottante ou située au-dessus de l'élément de conteneur de défilement.
Lorsque la souris se déplace sur l'écran, on peut obtenir les coordonnées actuelles de la souris.
Dans ce cas, clientX et clientY sont les coordonnées actuelles de la souris par rapport à la fenêtre de visualisation, on peut considérer que si cette coordonnée est dans la plage d'un conteneur de défilement, alors ce conteneur est considéré comme le conteneur de défilement actif. La plage de coordonnées du conteneur peut être obtenue à l'aide de getBoundingClientRect.
Voici un exemple de code lorsque la souris se déplace sur l'élément .left :
if (e.clientX>l.left && e.clientX<l.right && e.clientY>l.top) { // Entrez dans l'élément .left }
C'est effectivement possible, mais en considérant que les deux éléments de conteneur de défilement occupent presque toute la surface de l'écran, l'aire à surveiller pour mousemove est assez grande, ce qui pourrait exiger une performance élevée. Alors, en fait, on peut utiliser l'événement mouseover, il suffit de surveiller si la souris entre dans un élément de conteneur de défilement, et cela évite également de faire des jugements de coordonnées comme ci-dessus.
addEventListener('mouseover',function(){ // Entrer à l'intérieur de l'élément conteneur de défilement .left )
Lorsque l'élément conteneur de défilement qui a été défilé avec la souris est déterminé, il suffit de traiter l'événement de défilement de ce conteneur, et l'événement de défilement du conteneur de défilement suivant ne doit pas être traité.
Eh, l'effet est très bon, et les performances sont également bonnes, parfait, on peut finir maintenant~
Défilement proportionnel
Tous les exemples ci-dessus sont dans le cas où la hauteur du contenu des deux éléments conteneurs de défilement est complètement identique, qu'en est-il si la hauteur du contenu des deux éléments conteneurs de défilement est différente ?
C'est ainsi que cela fonctionne :
Il est visible que, en raison de la différence de hauteur du contenu des deux éléments conteneurs de défilement, la valeur maximale de scrollTop est également différente, ce qui entraîne que lorsque un élément avec une valeur de scrollTop plus petite atteint le bas, l'autre reste à la moitié, ou lorsque un élément avec une valeur de scrollTop plus grande atteint la moitié, l'autre est déjà au bas.
Ce type de situation est très courant, par exemple, lorsque vous écrivez en markdown, une étiquette de titre de premier niveau # dans le mode d'édition occupe généralement une hauteur inférieure à celle du mode aperçu, ce qui entraîne une inégalité de hauteur de défilement des deux côtés.
Donc, si on prend également ce cas en compte, on ne peut pas simplement fixer la valeur scrollTop des deux éléments conteneurs de défilement de manière aussi simple.
Bien que la hauteur du contenu du conteneur de défilement ne puisse pas être fixée, il y a un point qui peut être déterminé, c'est que la hauteur maximale de défilement de la barre de défilement, ou la valeur de scrollTop, doit être en relation avec la hauteur du contenu du conteneur de défilement et la hauteur du conteneur lui-même.
Comme il faut connaître la hauteur du contenu du conteneur de défilement et qu'il y a une barre de défilement, il faut ajouter un élément enfant à cet élément conteneur, la hauteur de l'élément enfant n'est pas limitée, c'est la hauteur du contenu du conteneur de défilement, la hauteur du conteneur est fixe, et le défilement en surplus est possible.
<div id="container"> <div class="left"> <div class="child"></div> </div> <div class="right"> <div class="child"></div> </div> </div>
Exemple de structure ci-dessous :
Par mes observations, inferences et vérifications pratiques, j'ai déterminé leur relation, qui est très simple, c'est-à-dire les opérations d'addition et de soustraction de base :
La hauteur maximale de défilement de la barre de défilement (scrollTopMax) = La hauteur du contenu du conteneur de défilement (c'est-à-dire la hauteur des éléments enfants ch) - La hauteur du conteneur de défilement lui-même (c'est-à-dire la hauteur de l'élément conteneur ph)
C'est-à-dire
C'est-à-dire, si l'height du contenu du conteneur de défilement (c'est-à-dire la hauteur des éléments enfants ch) et la hauteur du conteneur de défilement lui-même (c'est-à-dire la hauteur de l'élément conteneur ph) ont été déterminées, alors on peut必定确定 la hauteur maximale de défilement de la barre de défilement (scrollTop), et ces deux valeurs de hauteur sont généralement accessibles, donc on peut obtenir scrollTop
Par conséquent, pour que deux éléments de conteneur de défilement suivent proportionnellement en haut et en bas, c'est-à-dire que l'un des éléments atteint le haut ou le bas, l'autre élément peut également atteindre le haut ou le bas correspondant, il suffit de obtenir la proportion (scale) de la valeur maximale de scrollTop entre les deux conteneurs de défilement.
Une fois que le scale est déterminé, lors du défilement en temps réel, il suffit de récupérer le scrollTop du conteneur de défilement actif.1 , vous pouvez obtenir le scrollTop correspondant à un autre conteneur de défilement suivant.2 :
Une fois que les idées sont claires, écrire le code devient une tâche facile, et l'effet est le suivant :
Très fluide~
Résumé
Les besoins ont déjà été réalisés, mais peuvent nécessiter des modifications selon les circonstances pratiques. Par exemple, si vous écrivez une page d'édition et d'aperçu en ligne markdown, vous devez mettre à jour la valeur de scale en temps réel en fonction de la hauteur du contenu entré. Cependant, le travail principal est terminé, et les modifications mineures ne représentent pas un grand défi.
De plus, ce que j'ai décrit dans cet article ne s'applique pas seulement aux éléments de conteneur de défilement suivants, mais peut également être étendu. Le suivi du défilement entre plus d'éléments peut être réalisé suivant les idées de cet article. Cet article n'a été spécifiquement détaillé pour deux éléments pour faciliter l'explication.
Résumé
Ce que j'ai mentionné ci-dessus est l'effet de suivi de défilement synchronisé de plusieurs barres de défilement natives que j'ai présenté aux éditeurs. J'espère que cela peut vous aider. Si vous avez des questions, n'hésitez pas à laisser un message, je répondrai à temps. Je remercie également tout le monde pour le soutien au tutoriel d'alarme !
Déclaration : Le contenu de cet article est来源于网络,et appartient à ses auteurs respectifs. Le contenu est apporté par les utilisateurs d'Internet et téléversé spontanément. Ce site ne détient pas de droits de propriété, n'a pas été édité par l'homme, et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de droits d'auteur, vous pouvez envoyer un e-mail à : notice#w.3codebox.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation et fournir des preuves. Une fois vérifié, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.).