Smooth scroll to selection position?

Hi Everyone!

I’m trying to implement a feature where the editor will smoothly scroll to a text selection.

I have figured out that this bit of code will make the editor jump to the selected start position:

view.dispatch({
  selection: { 
    anchor: selectionStartPosition
  },
  scrollIntoView: true,
});

However, what I would like to do is smoothly scroll it to that position.

I have figured out that this bit of of code will give me a line object with these properties: from, to, number (the line number) and text (the text on that line.)

const line =  view.state.doc.lineAt(selectionStartPosition)

This is very useful!

So I think I’m close but the missing part of the puzzle that I need to figure out is:

How to gradually update the scroll position of the editor’s container from the old position to this new position?

I believe that would need to capture the current scroll position (in px?) and also the new scroll position (also in px?) and then update the scroll position in a tween animation.

Could anyone point me to where I should look to find how to find those start and end scroll positions?

Thank you!

You can get the current scroll position with view.scrollDOM.scrollTop. The desired scroll position you’d have to compute based on the position you want to see (view.coordsAtPos) and the editor rectangle (view.scrollDOM.getBoundingClientRect).

I’m trying to implement a smooth scroll with view.scrollDOM.scrollTo({ top, behavior: 'smooth' }); but view.coordsAtPos(firstLine.from) is returning null.

I’m noticing that the line I’m trying to scroll to is not in the DOM (yet). Is there another way to get it’s y position?

const firstLine = view.state.doc.line(lineNumber);
const {top} = view.coordsAtPos(firstLine.from); // can return null

view.scrollDOM.scrollTo({ top, behavior: 'smooth' });

view.lineBlockAt should work for out-of-viewport positions, though it may be an estimate, rather than a precise value if they (or other content between them and the current scroll position) haven’t been drawn before.

Thank you, that seems to work great!

thus might work

const f= view.state.doc.line(lineNumber);
const {qq} = view.coordsAtPos(f.from); // can return null

view.scrollDOM.scrollTo({ qq, behavior: 'smooth' });```

or this python minifier