I want to export a PowerPoint presentation using HTML2Canvas. The export works when I have only one gridster-item, but it doesn’t work when I have two or more. Can you help me fix this issue?
Even when it captures two or more gridster-items, it only captures half of the div. This is the issue I’m facing.
<div>
<gridster *ngIf="widgets?.length" [options]="options"
<gridster-item *ngFor="let widget of widgets" [item]="widget">
<ng-container [app-widget]="{ item: widget }"></ng-container>
</gridster-item>
</gridster>
</div>
<button mat-raised-button (click)="pptExport()">Export PPT</button>
// Export Function where my components there
async pptExport(): Promise<void> {
const gridster = document.querySelector('gridster');
if (!gridster) {
console.log('Gridster element not found.');
return;
}
const gridsterItems = gridster.querySelectorAll('gridster-item');
if (gridsterItems.length === 0) {
console.log('No gridster items found.');
return;
}
const itemsArray = Array.from(gridsterItems);
itemsArray.pop();
try {
await this.exportPPT.exportToPpt(itemsArray as HTMLElement[], this.pagename);
} catch (error) {
console.error('Error exporting to PowerPoint:', error);
}
}
// Services
import { Injectable } from '@angular/core';
import html2canvas from 'html2canvas';
import pptxgen from 'pptxgenjs';
@Injectable({
providedIn: 'root'
})
export class ExportPPTService {
constructor() { }
private captureElement(element: HTMLElement): Promise<HTMLCanvasElement> {
return new Promise((resolve, reject) => {
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => {
html2canvas(element, { scrollY: -window.scrollY }).then((canvas) => {
resolve(canvas);
}).catch((error) => {
reject(error);
});
}, 2000); // Increased timeout to ensure element is rendered
});
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
private async captureAllElements(elements: HTMLElement[]): Promise<{ canvas: HTMLCanvasElement, rect: DOMRect }[]> {
const results: { canvas: HTMLCanvasElement, rect: DOMRect }[] = [];
for (const element of elements) {
try {
const canvas = await this.captureElement(element);
const rect = element.getBoundingClientRect();
results.push({ canvas, rect });
} catch (error) {
console.error('Error capturing element:', error);
}
await this.sleep(2000); // Wait for 2 seconds between captures
}
return results;
}
async exportToPpt(containers: HTMLElement[], headerName: string): Promise<void> {
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_WIDE';
pptx.defineSlideMaster({
title: 'MASTER_SLIDE',
background: { color: 'FFFFFF' },
objects: [
{
image: {
x: 11.3,
y: 6.4,
w: 1.67,
h: 0.65,
path: 'assets/SCRAII_Logo.png',
},
},
],
slideNumber: { x: 0.3, y: '90%' },
});
const results = await this.captureAllElements(containers);
let slide = pptx.addSlide({ masterName: 'MASTER_SLIDE' });
const margin = 0.2;
const slideWidth = 13.33 - (2 * margin);
const addHeader = (slide: pptxgen.Slide) => {
slide.addText(
[{ text: headerName, options: { color: '#212529', fontSize: 14, fontFace: 'Poppins Black' } }],
{ x: margin, y: margin }
);
};
addHeader(slide);
results.forEach(({ canvas, rect }, index) => {
const itemWidth = rect.width / 96;
const itemHeight = rect.height / 96;
const xPosition = rect.left / 96;
const yPosition = rect.top / 96;
let adjustedWidth = itemWidth;
let adjustedHeight = itemHeight;
if (itemWidth > slideWidth) {
const scaleFactor = slideWidth / itemWidth;
adjustedWidth = slideWidth;
adjustedHeight = itemHeight * scaleFactor;
}
slide.addImage({
data: canvas.toDataURL(),
x: xPosition + margin,
y: yPosition + margin,
w: adjustedWidth,
h: adjustedHeight
});
});
pptx.writeFile({ fileName: headerName + '.pptx' });
}
}