“Angular – HTML Canvas在开始绘制时变为黑色”

huangapple go评论79阅读模式
英文:

Angular - HTML Canvas turns black when I start drawing

问题

I'm building an Angular app where I intend to let the user draw text fields over PDF pages. For this, I'm using ng2-pdf-viewer library and I have a PDF page component that will hold a PDF page, as well as its corresponding HTML canvas element.

The problem I'm facing is that the canvas turns black when I start drawing on the respective PDF page. Although I am able to draw successfully, this means the whole page background turns to black.

Here is how it looks (the PDF page with content is behind that black background):

“Angular – HTML Canvas在开始绘制时变为黑色”

My page component code is the following:

export class PdfPreviewPageComponent {
    @Input() pdfSrc: string = '';
    @Input() pdfPageNumber!: number;

    @ViewChild('pdfViewer', { static: false, read: ElementRef }) pdfViewerRef!: ElementRef;

    private canvas!: HTMLCanvasElement;
    private ctx: CanvasRenderingContext2D | null = null;
    private isDrawing: boolean = false;
    private startX!: number;
    private startY!: number;

    // UPDATE: changed from getting the canvas via input and using ngOnChanges to
    // using the (page-rendered) event provided by ng2-pdf-viewer library
    onPageLoaded(event: Event) {
        if (!this.canvas) {
            this.canvas = this._document.getElementsByTagName('canvas')[this.pdfPageNumber - 1];
            this.ctx = this.canvas.getContext('2d');

            if (this.ctx) {
                this.ctx.fillStyle = 'red';
                this.ctx.lineWidth = 2;
                this.handleCanvasEvent();
            }
        }
    }
    ...
    ...
}

How can I avoid the canvas turning completely black? I don't want to hide the content of the PDF page as the whole purpose is for the user to draw text fields (rectangles) where they may see fit.

Here is the stackblitz project.

英文:

I'm building an Angular app where I intend to let the user draw text fields over PDF pages. For this, I'm using ng2-pdf-viewer library and I have a PDF page component that will hold a PDF page, as well as its corresponding HTML canvas element.

The problem I'm facing is that the canvas turns black when I start drawing on the respective PDF page. Although I am able to draw successfully, this means the whole page background turns to black.

Here is how it looks (the PDF page with content is behind that black background):

“Angular – HTML Canvas在开始绘制时变为黑色”

My page component code is the following:

export class PdfPreviewPageComponent {
    @Input() pdfSrc: string = '';
    @Input() pdfPageNumber!: number;

    @ViewChild('pdfViewer', { static: false, read: ElementRef }) pdfViewerRef!: ElementRef;

    private canvas!: HTMLCanvasElement;
    private cx: CanvasRenderingContext2D | null = null;
    private isDrawing: boolean = false;
    private startX!: number;
    private startY!: number;

    // UPDATE: changed from getting the canvas via input and using ngOnChanges to
    // using the (page-rendered) event provided by ng2-pdf-viewer library
    onPageLoaded(event: Event) {
	    if (!this.canvas) {
		    this.canvas = this._document.getElementsByTagName('canvas')[this.pdfPageNumber - 1];
		    this.ctx = this.canvas.getContext('2d');

		    if (this.ctx) {
			    this.ctx.fillStyle = 'red';
			    this.ctx.lineWidth = 2;
			    this.handleCanvasEvent();
		    }
	    }
    }

    private handleCanvasEvent() {
	    this.canvas.addEventListener('mousemove', (event) => this.onMouseMove(event));
	    this.canvas.addEventListener('mousedown', (event) => this.onMouseDown(event));
	    this.canvas.addEventListener('mouseup', (event) => this.onMouseUp(event));
    }

    private onMouseDown(event: MouseEvent) {
	    this.isDrawing = true;
	    this.startX = event.clientX - this.canvas.getBoundingClientRect().left;
	    this.startY = event.clientY - this.canvas.getBoundingClientRect().top;
    }

    private onMouseMove(event: MouseEvent) {
	    if (!this.isDrawing) {
		    return;
	    }

	    const currentX = event.clientX - this.canvas.getBoundingClientRect().left;
	    const currentY = event.clientY - this.canvas.getBoundingClientRect().top;
	    const width = currentX - this.startX;
	    const height = currentY - this.startY;

	    this.clearCanvas();
	    this.drawRectangle(this.startX, this.startY, width, height);
    }

    private onMouseUp(event: MouseEvent) {
	    this.isDrawing = false;
    }

    private clearCanvas() {
	    if (this.cx) {
		    this.cx.clearRect(0, 0, this.canvas.width, this.canvas.height);
	    }
    }

    private drawRectangle(x: number, y: number, width: number, height: number) {
	    if (this.cx) {
		    this.cx.strokeRect(x, y, width, height);
	    }
    }
    ...
    ...
}

How can I avoid the canvas turning completely black? I don't want to hide the content of the PDF page as the whole purpose is for the user to draw text fields (rectangles) where they may see fit.

Here is the stackblitz project.

答案1

得分: 0

问题在于我试图使用和操作ng2-pdf-viewer库在每个PDF查看器元素上使用的画布。这是呈现PDF内容的画布,因此一旦在此画布上调用任何清除画布的方法(如clearRect()),您将不可避免地删除所有PDF页面内容。

正确的方法是创建自己的画布元素,并将它们叠加在各自的页面上,使用绝对或相对定位,并确保每个画布位于堆叠顺序的顶部,使用z-index

英文:

The problem is that I was trying to use and manipulate the canvas that the ng2-pdf-viewer library uses on each of its PDF viewer elements. This is the canvas that renders the PDF content, so once you call any canvas clearing methods (such as clearRect()) on this canvas, you will inevitably delete all of the PDF page content.

The correct approach is to create your own canvas elements and overlay them on top of their respective pages, using absolute or relative positioning and making sure each canvas is on top of the stacking order with z-index.

huangapple
  • 本文由 发表于 2023年5月25日 18:44:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76331423.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定