Angular 6用html2canvas导出PDF时indicator widget无法导出问题求解
@Injectable({
providedIn: "root",
})
export class WidgetsExportService {
private readonly options = {
backgroundColor: "#ffffff",
logging: false,
};
private _exportCardSubject$ = new Subject
constructor(
@Inject(DOCUMENT) private document
) {}
...
public exportCard(
originalContent: HTMLElement,
...
) {
this.globalProgressService.showProgress();
this.doExportCard(
originalContent,
...
);
}
...
private getContentRows(originalContent: HTMLElement): HTMLElement[] {
return Array.from(
originalContent.querySelectorAll("#overview-dashboard > .content-row")
);
}
private doExportCard(
originalContent: HTMLElement,
...
) {
const pagePromises: Promise
const pageWrappers: HTMLElement[] = [];
const clonedContent: HTMLElement = originalContent.cloneNode(
true
) as HTMLElement;
const rowWidthWithPadding = originalContent.offsetWidth + 26;
const rowHeightWithPadding = originalContent.offsetHeight + 26;
const wrapper: HTMLElement = this.createWrapper(
rowWidthWithPadding,
rowHeightWithPadding
);
wrapper.appendChild(clonedContent);
this.addWrapperToDocument(wrapper);
pagePromises.push(html2canvas(wrapper, this.options));
pageWrappers.push(wrapper);
const headerFooterWrapper: HTMLElement = this.createWrapper(1300); pageWrappers.push(headerFooterWrapper); this.createHeaderFooter(headerFooterWrapper, headerConfig, filterMap); Promise.all([ html2canvas(document.getElementById("pdf-header")), html2canvas(document.getElementById("pdf-filters")), ]) .then(([headerCanvas, filtersCanvas]) => { const copyrightText = headerConfig.copyrightText; headerFooterWrapper.appendChild( this.createFooter(1, 1, copyrightText, formattedDate) ); pagePromises.push( html2canvas(document.getElementById("pdf-footer" + 1)) ); this.renderPages( pagePromises, fileName, headerCanvas, filtersCanvas, pageWrappers, pdfPassword ); }) .catch((e) => { this.removeWrappersFromDocument(pageWrappers); throw new Error(e); });
}
}
可忽略颜色差异问题,我只需要让该indicator widget也能被正常导出。 --- ## 解决方案 该问题的核心原因是`indicator widget`属于动态渲染的组件,你克隆DOM节点的操作仅能复制静态HTML结构,无法复制组件运行时生成的Canvas/SVG内容、计算后样式,导致html2canvas捕获克隆节点时识别不到对应内容。可按以下两种方案解决: - 优先采用直接渲染原DOM节点的方案:取消克隆节点的逻辑,直接对页面上真实的原内容节点调用html2canvas截图。如果担心截图过程中页面出现闪烁,可以给原节点临时加一层和页面背景一致的半透明遮罩,截图完成后再移除遮罩即可。 - 如果必须使用克隆节点的逻辑,补充以下配置: 1. 修改html2canvas的基础配置,开启动态内容渲染支持: ```typescript private readonly options = { backgroundColor: "#ffffff", logging: false, useCORS: true, scale: window.devicePixelRatio, foreignObjectRendering: true, };
- 克隆节点插入到wrapper之后,新增100~200ms的延迟再调用html2canvas,给动态内容预留渲染时间。
- 如果
indicator widget是基于Canvas实现的,手动把原组件Canvas的内容绘制到克隆节点对应的Canvas元素上,再执行截图操作。
内容的提问来源于stack exchange,提问作者Tanzeel

