Single Document Scroll Renderer
The SingleDocumentScrollRenderer
is a renderer with a scrolling view. It displays one Content Document at a time and the user is able to scroll through the contents.
Navigation
The SingleDocumentScrollRenderer
can be navigated by using the navigation methods provided by the ReaderView, as well as ReaderView.scrollBy()
and by scrolling manually. ReaderView.previous()
and ReaderView.next()
will navigate to the previous/next Content Document.
Reading Position
The Reading Position will be updated normally after a navigation to a Locator. It will also be updated every time the user scrolls inside the document.
The Reading Area
The Reading Area defines the part of the renderer's visible area that will be used for calculations related to Reading Positions. If a SyncMediaPlayer
is attached to the ReaderView and managed ReaderView synchronization is enabled, the Reading Area also has an impact on how the renderer synchronizes its visible content with the SyncMediaPlayer.

After a navigation using ReaderView.goTo()
, or after scrolling so that the old Reading Position is outside the visible range, the new Reading Position will match the top of the Reading Area.
When SyncMediaPlayer
playback causes the Reading Position to change, the renderer will, if necessary, automatically scroll to keep the Reading Position inside the Reading Area.
Changing the size of the Reading Area can be done by using the ISingleDocumentScrollRendererOptions
, either by passing them as a parameter when creating a new SingleDocumentScrollRenderer
or by using the setOptions()
method. For more details see the API documentation.
Synchronization with a SyncMediaPlayer
There are a few different strategies for using the SingleDocumentScrollRenderer
with a SyncMediaPlayer
.
The recommended strategy is to set SyncMediaPlayer.setManagedReaderViewSynchronization({enabled: true})
and let the Colibrio Reading System manage the synchronization. Using this method has a few recommended settings to keep the user experience as smooth as possible.
syncMediaPlayer.setManagedReaderViewSynchronizationOptions({
enabled: true,
alwaysSeekToSegmentStart: true
})
syncMediaPlayer.setReaderViewSynchronizationWaitBehavior(SyncMediaReaderViewSynchronizationWaitBehavior.DONT_WAIT)
Setting the alwaysSeekToSegmentStart
to true ensures that the SyncMediaPlayer
will always start playing from the start of a segment, even after scrolling so that the Reading Position ends up in the middle of a segment. This, however, may cause the SyncMediaPlayer
to attempt playing content that is before the visible content. Therefore it is also recommended to set the SyncMediaReaderViewSynchronizationWaitBehavior.DONT_WAIT
.
Another strategy is to let the SyncMediaPlayer
play independently of the ReaderView
, using SyncMediaPlayer.setManagedReaderViewSynchronization({enabled: false})
and manually call SyncMediaPlayer.attemptReaderViewSynchronization()
when the user presses a button to either navigate the renderer to the current SyncMediaTimelinePosition
or seek the SyncMediaPlayer
to the current Reading Position.
Scroll Events
A list of the scroll related events. Please refer to the API documentation for more details.rendererScrollCanceled
rendererScrollEnded
rendererScrollHeightChanged
rendererScrollStarted
Common use cases
Check if the renderer is scrolled all the way down
The following code example shows you how you can detect if the renderer has scrolled to the bottom of a document.
const mainView: IReaderView;
let isAtBottom = false;
/**
* Function to see if the renderer has scrolled to the bottom of the current document.
*/
function checkIfScrolledToBottom(readerView: IReaderView): void {
const scrollState = readerView.getScrollState();
if (!scrollState) {
return;
}
if (scrollState.rendererClientHeight + scrollState.scrollTop >= scrollState.scrollHeight) {
isAtBottom = true;
} else {
isAtBottom = false;
}
}
/*
* You need to listen to both events to make sure that it will trigger even when there is a short
* document so there is no scrolling happening.
*/
mainView.addEngineEventListener('rendererScrollEnded', evt => {
checkIfScrolledToBottom(evt.readerView);
});
mainView.addEngineEventListener('rendererScrollHeightChanged', evt => {
checkIfScrolledToBottom(evt.readerView);
});