The main challenge in rendering the text into fixed container slides lies in calculating the appropriate points to split the text into pages, so I needed to come up with a strategy for page breaking.
My initial idea was to detect the on-screen space occupied by each letter and divide the entire text into an array of page blocks. However, this approach has complications: in fonts that are not monospaced
, each letter occupies a different amount of space, making it overly complex and inefficient to measure every letter in various fonts and sizes.
Therefore, I decided to identify the first word on each new page. To simplify the process, let's temporarily set aside styling elements like headings for a while and imagine a scenario where we deal exclusively with plain text:
I divided the entire text into an array of individual words, rendering each word separately to identify the first word of each new page. Subsequently, I saved the indexes of these first words in an array named breakpoints
Now, let's bring back styles. Headings and body text will not share the same line. So, I parsed the input text line by line and converted it into an array of objects like this:
const contentBlocks = [
{ style: "heading": words: ["Prins"] },
{ style: "body": words: ["Mijn", "moeder", "is", "zevenenzeventig"] },
...
...
]
As a result of these changes, the breakpoints are updated accordingly:
Given the breakpoints
consisting of line indexes along with word indexes, it becomes straightforward to write a function that will return a chunk of the array of contentBlocks
for a given page index.
type BreakPoint = string // 1:15
type ContentBlock = Array<{ style: string; words: string[] }>
function getPageBlocksByBreakPoint(contentBlocks: ContentBlocks, start: BreakPoint, End: BreakPoint): ContentBlocks
Graph
Problems
Rendering the entire 300-page book directly into the DOM for detecting page breaks would indeed be highly resource-intensive, particularly in terms of memory usage. Therefore, it's essential to optimize the algorithm to address this challenge.
Also, resizing the container size, font size, font style, or even a change in the font type, would require re-generating breakPoints