Angular9实现canvas清空按钮点击时报clearCanvas不是函数问题求助
问题原因
- 你将
clearCanvas方法定义在ngAfterViewInit的内部作用域中,Angular模板的事件绑定只能调用组件类的公开实例方法,无法访问函数内部的局部方法,因此会报方法不存在的错误。 - 你已经声明了
@ViewChild('canvas')来获取canvas元素,但代码中仍使用document.getElementById查找DOM,同时绘图所需的上下文、背景色等变量都只存在于ngAfterViewInit的局部作用域,其他方法无法访问。 - 模板中canvas只设置了id属性,没有加
#canvas模板引用标记,导致@ViewChild无法正常获取到元素实例。
修复方案
第一步 修改组件TS代码
把需要共享的变量提为组件属性,将clearCanvas改为组件实例方法,优化DOM获取逻辑:
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'app-draw-on-image', templateUrl: './draw-on-image.component.html', styleUrls: ['./draw-on-image.component.scss'] }) export class DrawOnImageComponent implements OnInit { @ViewChild('canvas', {static: false}) canvasRef: ElementRef<HTMLCanvasElement>; private context: CanvasRenderingContext2D; private startBackgroundColor = "white"; private drawColor = this.startBackgroundColor; private drawWidth = 2; private isDrawing = false; constructor() { } ngOnInit(): void { } ngAfterViewInit(){ const canvas = this.canvasRef.nativeElement; canvas.width = window.innerWidth - 60; canvas.height = 400; this.context = canvas.getContext("2d"); this.context.fillStyle = "white"; this.context.fillRect(0,0, canvas.width, canvas.height); canvas.addEventListener("touchstart", this.start.bind(this), false); canvas.addEventListener("touchmove", this.draw.bind(this), false); canvas.addEventListener("mousedown", this.start.bind(this), false); canvas.addEventListener("mousemove", this.draw.bind(this), false); canvas.addEventListener("touchend", this.stop.bind(this), false); canvas.addEventListener("mouseup", this.stop.bind(this), false); canvas.addEventListener("mouseout", this.stop.bind(this), false); } private changeColor(element){ this.drawColor = element.style.background; } private start(event){ this.isDrawing = true; const canvas = this.canvasRef.nativeElement; this.context.beginPath(); this.context.moveTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop); event.preventDefault(); } private draw(event){ if(this.isDrawing){ const canvas = this.canvasRef.nativeElement; this.context.lineTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop); this.context.strokeStyle = this.drawColor; this.context.lineWidth = this.drawWidth; this.context.lineCap = "round"; this.context.lineJoin = "round"; this.context.stroke(); } event.preventDefault(); } private stop(event){ if(this.isDrawing){ this.context.stroke(); this.context.closePath(); this.isDrawing = false; } event.preventDefault(); } // 公开方法,供模板调用 clearCanvas(){ const canvas = this.canvasRef.nativeElement; this.context.fillStyle = this.startBackgroundColor; this.context.clearRect(0, 0, canvas.width, canvas.height); this.context.fillRect(0, 0, canvas.width, canvas.height); } }
第二步 修改组件HTML代码
给canvas加上#canvas模板引用,同时将清空按钮的type改为button避免误触表单提交:
<div class="field"> <!-- 加上#canvas模板引用,供@ViewChild获取 --> <canvas id="canvas" #canvas></canvas> <div class="tools"> <button type="button" class="button">Undo</button> <button type="button" (click)="clearCanvas()">Clear</button> </div> </div>
内容的提问来源于stack exchange,提问作者Mritunjay Sharma
相关产品推荐
相关产品推荐

