I also met this problem a few days ago.
Here is my solution
Here is three needed variable
- clientHeight, is the scroll block height
- For monaco, you should wrap it with a div, and get it by
divRef.current.clientHeight
- For div, you can simplely use
divRef.current.clientHeight
- scrollHeight, is the whole scrollable content height
- For monaco, you can get it by
editor.getScrollHeight()
- For div, you can use
divRef.current.scrollHeight
- scrollTop, is the top of scrollbar
- For monaco, you can get it by
editor.getScrollTop()
- For div, you can use
divRef.current.scrollTop
type ScrollNode = {
clientHeight: number
scrollHeight: number
scrollTop?: number
}
Then
- Calculate the above height of scroll bar in clientHeight
- Calculate the below height of scroll bar in clientHeight
- Then you can get three percenage of clientHeight (A/B/C of (A+B+C))
- Then the A part percentage is what you want of the unknown block(div/monaco) scrollTop of clientHeight, C part is for scrollBottom of clientHeight
┌ A ┐┌ B ┐┌ C ┐
|-----+++++++---------|
const computeScrollTopPercent = (known: Required<ScrollNode>, unknown: ScrollNode): number => {
let knownTopPercent = known.scrollTop / known.scrollHeight
let knownScrollbarPercent = known.clientHeight / known.scrollHeight
let knownTopPercentExcludeScrollbar = knownTopPercent / (1 - knownScrollbarPercent)[enter image description here][1]
let unknownScrollbarPercent = unknown.clientHeight / unknown.scrollHeight
let unknownTopPercent = (1 - unknownScrollbarPercent) * knownTopPercentExcludeScrollbar
return unknownTopPercent
// let accuracy = 100000
// return Math.round(unknownTopPercent * accuracy) / accuracy
}