preface

I need to add synchronous scrolling function to the Markodwn editor I am writing, but I did not find a good idea. I wrote one of my own.

Github has written libraries and more intuitive demos. Github

This article is mainly about the idea of implementation.

introduce

Synchronous scrolling can be implemented in a number of ways. Simply set htmlElement. scrollTop to equal, scroll bars to equal proportions, and title aligned scrolling (which I saw on Stackedit).

The main content of this article is the realization of synchronous scrolling title alignment.

Personally, I prefer title alignment because it is more user friendly than the other two.

In principle, title alignment is an improved version of equal scale scrolling. At their core, they determine scrolling distance by calculating the height ratio of the edit area to the preview area.

DEMO

Below is a GIF of the DEMO

Synchronize scrolling

You can see that as the scroll bar moves, the left and right sides scroll differently.

This looks a bit like equal scale scrolling, but it’s different. The difference is that equal scale scrolling depends on the height of the text on both sides, and the alignment of the heading depends on the height of the content below the heading.

Train of thought

# heading indicates the heading, and content indicates the content below the heading. I call title + content fragments.

Equal-scale scrolling I think is easier to understand by calculating the ratio of the height of the edit area to that of the preview area, and then calculating the scrolling distance based on that ratio.

Title alignment is a little more precise, changing the height of the edit and preview areas to the height of the title + the height of the content under the title (the height of the clip), and then calculating the scrolling distance based on the height of the current clip.

The MD height and HTML height in the diagram above are the height of the fragment we need. And it’s pretty clear that we can figure out how far we roll by taking the ratio of these two heights.

The specific process

  1. The first step is to edit the title information of the edit area and preview area. The data structure is as follows. Here witheditFragmentsInfoandpreFragmentsInfoInstead of
FragmentInfo: {
    pairId,         // The id used to match the title corresponding to the edit/preview area
    offsetTop,      // The offset distance from the top
    height          // The title plus the height of the content
}
Copy the code
  1. Then you need a method that can get the title block at the top of the current page, which is used heregetCurrentFragment()Instead of
  2. The next step is to send a message to the previewArea/previewArea in a scroll event notifying it that the scroll is about to start.
  3. After the other region receives it, do the following. (Assuming that the active scroll is the edit area and the passive scroll is the preview areaAnother area)
    1. First get the current title at the top, use the one mentioned abovegetCurrentHeading()To obtain.
    2. Then match the corresponding title in the preview area.
    3. According to both sidesheadingInfo.heightThe ratio of PI to PI plus PIheadingInfo.offsetTopThe value of is the preview areascrollTop.
  4. At this point, one synchronization is over. This process is bound to the element’s scroll event, which is triggered once for each scroll.
Synchronization issues

Because scrolling on one element leads to scrolling on another, this is bound to be an endless loop. So be sure to use judgment in rolling events to avoid endless loops.

This is a simple mutex method that supports mutex for more than two objects