在使用聚合物和pdf.js开发一些自定义元素来显示pdf文件时,我注意到在两个pdf文件之间显示和切换时出现内存泄漏。消耗的内存增长,我似乎无法弄清楚原因。为了观察内存更改,我在谷歌浏览器中使用堆快照。我们的想法是让铁列表显示单个页面,这些页面包含在另一个自定义元素中。
这是应该加载pdf文档的元素,将其显示为列表并将加载的pdfpageproxys传播到另一个自定义元素,然后应该显示它:
PDF一览viewer.html
<link rel="import" href="../polymer/polymer-element.html">
<link rel="import" href="../iron-list/iron-list.html">
<link rel="import" href="../layer-view/layer-view.html">
<link rel="import" href="../pdf-page-viewer/pdf-page-viewer.html">
<dom-module id="pdf-list-viewer">
<template>
<style>
iron-list {
width: 400ox;
height: 800px;
}
layer-view {
width: 100%;
min-height: 100%;
}
</style>
<iron-list items="[[pages]]" as="page">
<template>
<pdf-page-viewer pdf-page="[[page]]" canvas-width="800" />
</template>
</iron-list>
</template>
<script>
/**
* `pdf-list-viewer`
* Shows a pdf file as a scrollable list of individual pages
*
* @customElement
* @polymer
* @demo demo/index.html
*/
class PdfListViewer extends Polymer.Element {
static get is() { return 'pdf-list-viewer'; }
static get properties() {
return {
pdfUrl: {
type: Object,
observer: '_pdfUrlChanged'
},
pages: {
type: Array,
value: []
},
_loadingTask: Object
};
}
_pdfUrlChanged(newValue, oldValue) {
var self = this;
// Remove old pages
var destroyPromise = null;
if (this.pages.length !== 0) {
destroyPromise = this._loadingTask.destroy();
}
if(destroyPromise === null){
this._loadPdf(newValue);
} else{
destroyPromise.then(function(){
self._loadPdf(newValue);
});
}
}
_loadPdf(newUrl){
var self = this;
this.pdfUrl = newUrl;
this._loadingTask = PDFJS.getDocument({ url: newUrl });
this._loadingTask.then(function (pdfDoc) {
var pagePromises = Array.from(new Array(pdfDoc.numPages), (_, index) => pdfDoc.getPage(index + 1));
Promise.all(pagePromises).then(function (values) {
self.splice('pages', 0, self.pages.length, ...values);
});
}).catch(function (error) {
// TODO: handle error
alert(error.message);
});
}
}
window.customElements.define(PdfListViewer.is, PdfListViewer);
</script>
</dom-module>
这是一个只需要在画布上显示pdf并处理缩放的元素(这对于现在来说并不重要):
PDF的页面viewer.html
<link rel="import" href="../polymer/polymer-element.html">
<linkrel="import" href="../paper-spinner/paper-spinner.html">
<link rel="import" href="pdfjs.html">
<dom-module id="pdf-page-viewer">
<template>
<style>
</style>
<canvas id="pageCanvas" width="[[canvasWidth]]"></canvas>
<!-- Here should be a circular loading bar displaying that page is rendering -->
</template>
<script>
/**
* `pdf-page-viewer`
* Viewer to display a single pdf page using mozillas pdf.js library
*
* @customElement
* @polymer
* @demo demo/index.html
*/
class PdfPageViewer extends Polymer.Element {
static get is() { return 'pdf-page-viewer'; }
static get properties() {
return {
/**
* Page object as defined in pdfjs-dist library in lib/core/document.js.
*/
pdfPage: {
type: Object,
observer: '_pageChanged'
},
/**
* Width of the page canvas in pixel. Height will be calculated when showing the page.
*/
canvasWidth: Number,
_zoom: Number,
/**
* Displays wether or not a page rendering is being processed.
*/
pageRenderingInProgress: {
type: Boolean,
value: false,
}
};
}
constructor(){
super();
this._boundChangeListener = this.zoom.bind(this);
}
connectedCallback() {
super.connectedCallback();
window.addEventListener('zoom', this._boundChangeListener);
}
disconnectedCallback(){
super.disconnectedCallback();
window.removeEventListener('zoom', this._boundChangeListener);
}
_pageChanged(newValue, oldValue) {
this.pdfPage = newValue;
this._showPage();
}
// Load and render a specific page of the PDF
_showPage() {
this.pageRenderingInProgress = true;
var self = this;
// As the canvas is of a fixed width we need to set the scale of the viewport accordingly
var scale_required = this.$.pageCanvas.width / this.pdfPage.getViewport(1).width;
// Get viewport of the page at required scale
var viewport = this.pdfPage.getViewport(scale_required);
// Set canvas height
this.$.pageCanvas.height = viewport.height;
var renderContext = {
canvasContext: self.$.pageCanvas.getContext('2d'),
viewport: viewport
};
// Render the page contents in the canvas
this.dispatchEvent(new CustomEvent('pageRenderingStarted'));
this.pdfPage.render(renderContext).then(function () {
self.pageRenderingInProgress = false;
self.dispatchEvent(new CustomEvent('pageRenderingFinished'));
});
}
zoom(event) {
this._zoom = event.detail.newValue;
this.$.pageCanvas.width = this.canvasWidth * this._zoom;
this._showPage();
}
}
window.customElements.define(PdfPageViewer.is, PdfPageViewer);
</script>
</dom-module>
请记住,我是网络开发中的新生物(以及聚合物和pdf.js),所以可以随意批评你发现的每一件小事,这样我就可以在这方面有所改进。 非常感谢每一个帮助!
修改
我使用chrome dev工具监视this webcomponent中pdf-viewer演示的内存使用情况,并在拍摄内存堆快照时注意到相同的内存泄漏。只需转到https://www.webcomponents.org/element/telecomsante/pdf-viewer/demo/demo/index.html,单击367页的pdf文件,在保管箱中切换到antoher pdf并切换回367 pdf文档。再次通过它们后,您将获得以下增加:
22,5 MB(第1/367页已打开) - &gt;
52,7 MB(点击文档的每一页) - &gt;
55,5 MB(在列表中打开另一个文档并单击页面) - &gt;
69,8 MB(打开367页pdf并再次点击所有这些页面)
有什么想法吗? 要重新创建,只需