-
Hi there, |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Implementing multiple pages supportIntroductionI will walk you through the steps to implement multiple pages support. Stacks to implement multiple pages support :
PrerequisitesBefore you begin, ensure you have the following:
Steps1. Define a save file formatI chose to work with JSON files, but you can choose any format that suits your needs.
type PageRecord = {
objects: FabricObject[];
...otherProperties
}; 2. Document & Page instancesDocument instance will be responsible for managing the gobal state of the document, and Page instance will be responsible for managing the state of the current instanciated page. example of Document instance (using MobX): class DocumentInstance {
public Document: PageRecord[] = [];
constructor() {
makeAutoObservable(this); // mobx
}
setDocument(document: PageRecord[]) {
this.Document = document;
}
getDocument() {
return toJS(this.Document); // toJS is a mobx function to convert the observable object to a plain object
}
setDocumentPage(pageIndex: number, page: PageRecord) {
this.Document[pageIndex] = page;
}
getDocumentPage(pageIndex: number) {
return toJS(this.Document[pageIndex]);
}
}
export default new DocumentInstance(); example of Page instance (using MobX): class PageInstance {
page: PageRecord | null = null;
pageIndex: number = 0;
constructor() {
makeAutoObservable(this); // mobx
}
setPage(page: PageRecord) {
this.page = page;
}
setPageIndex(pageIndex: number) {
this.pageIndex = pageIndex;
}
getPage(): PageRecord {
return toJS(this.page); // toJS is a mobx function to convert the observable object to a plain object
}
getPageIndex(): number {
return this.pageIndex;
}
}
export default new PageInstance(); 3. Update the pages & document instancesUpdate the class PageInstance {
page: PageRecord | null = null;
pageIndex: number = 0;
constructor() {
makeAutoObservable(this); // mobx
}
// ... previous methods
/**
* Update the DOCUMENT instance with the page instance
* [DOCUMENT] <- [PAGE]
* @returns void
*/
updatePageInstance(): void {
this.page = documentInstance.getDocumentPage(this.pageIndex);
}
/**
* Update the page instance with the DOCUMENT instance
* [PAGE] <- [DOCUMENT]
* @returns void
*/
updateDocumentInstance(): void {s
documentInstance.setDocumentPage(this.pageIndex, this.page);
}
} 4. Save the canvas state to the page instanceYou will need to save the canvas state to the page instance when switching between pages. class SaveService {
private canvas: fabric.Canvas
private page: PageRecord
constructor() {
this.canvas = EditorStore.canvas // fabric canvas instance
this.page = PageInstance.getPage()
}
async saveCanvasState(): Promise<void> {
let canvasToPage = this.canvas.toObject(propertiesToInclude)
if(canvasToPage.length === 0) return
this.page.objects = canvasToPage
try {
await this.savePage()
} catch (error) {
console.error(error)
}
}
private async savePage(): Promise<void> {
try {
await new Promise( (resolve, reject) => {
try {
// update the page instance with the new page object
PageInstance.setPage(this.page)
resolve('page instance updated')
} catch (error) {
reject(error)
}
})
} catch (error) {
console.error('error while updating page instance', error)
}
try {
await new Promise( (resolve, reject) => {
try {
// update the document instance with the new page instance
PageInstance.updateDocumentInstance()
resolve('model instance updated')
} catch (error) {
reject(error)
}
})
} catch (error) {
console.error('error while updating model instance', error)
}
}
} you will need to call 5. Display and switch between pagesYou will need to display the pages and switch between them. 1 - Map trough the document instance to display the pagesWe will use observer from mobx-react to observe the changes in the document instance. const Pages = observer(() => {
const document = documentInstance.getDocument()
return (
<div>
{document.map((page, index) => (
<Page key={index} page={page} pageIndex={index} onPageSelect={handleChangePage} />
))}
</div>
)
}) 2 - Change the page instance when switching between pages const handleChangePage = (pageIndex: number) => {
const saveService = new SaveService()
const renderService = new RenderService() // service to render the canvas
saveService.saveCanvasState() // save the current canvas state to the current page instance
PageInstance.updateDocumentInstance() // update the document instance with the current page instance
PageInstance.setPageIndex(pageIndex) // set the new page index
PageInstance.updatePageInstance() // update the page instance with the new page instance
renderService.render() // render the new page instance
} 6. Render the canvasYou will need to render the canvas when switching between pages. class RenderService {
private canvas: fabric.Canvas
private page: PageRecord
private pageIndex: number
constructor() {
this.canvas = EditorStore.canvas // fabric canvas instance
this.page = PageInstance.getPage()
this.pageIndex = PageInstance.getPageIndex()
}
async render(): Promise<void> {
this.canvas.clear()
this.renderWorkspace()
try {
await this.renderPageObjects(this.page)
} catch (error) {
console.error(error)
}
this.canvas.renderAll()
}
private renderWorkspace(): void {
// build my worspace (not the subject of this example)
}
private async renderPageObjects(page: PageRecord): Promise<void> {
const renderedObjectIds = new Set<string>()
const objectBuilder = new ObjectBuilder() // not the subject of this example
for (const obj of page.objects) {
if (renderedObjectIds.has(obj.id)) {
continue
}
try {
await objectBuilder.makeObject(obj) // build the object from JSON
renderedObjectIds.add(obj.id)
} catch (error) {
console.error(error)
}
}
}
} 7. Initialize the document instanceYou will need to initialize the document instance when the application starts.
const createDocument = (nb_pages: number) => {
const pageBuilder = new PageBuilder() // not the subject of this example
let document = []
let page: Partial<PageRecord> = {} // build the first page
for (let i = 0; i < nb_page; i++) {
page = pageBuilder.buildPage()
document.push(page as PageRecord)
}
return document
}
const loadDocument = (document: PageRecord[], index) => {
documentInstance.setModel([]) // initialize the document instance
documentInstance.setModel(document) // set the document instance with the new document
PageInstance.setPageIndex(index) // set the page index
PageInstance.setPageInstance(document[index]) // set the page instance
PageInstance.updatePageInstance() // update the page instance with the new page instance
} ConclusionBy following these steps, you can successfully implement multiple pages support in your project. You can adapt this method to your needs and use any state management library you prefer. I hope this guide was helpful to you. Say me if you have any questions or suggestions. |
Beta Was this translation helpful? Give feedback.
Implementing multiple pages support
Introduction
I will walk you through the steps to implement multiple pages support.
This Method is based on my experience and may not be the best solution for your project. You can adapt it to your needs.
Stacks to implement multiple pages support :
Prerequisites
Before you begin, ensure you have the following:
Steps
1. Define a save file format
I chose to work with JSON files, but you can choose any format that suits your needs.
You will need to save and restore t…