You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular9 Canvas实现多边形绘制与顶点拖拽时mouse对象未定义问题求解

Angular Canvas可编辑多边形mouse对象undefined问题解决方案

问题原因

  1. 核心原因为update方法的this指向丢失:你将update作为回调传入requestAnimationFrame时,普通函数在浏览器API调用时this默认指向全局对象(严格模式下为undefined),所以方法内访问this.mouse时无法匹配到组件实例的mouse对象,返回undefined。
  2. 次要问题:polygon对象的draw等内部方法中直接使用this.context访问画布上下文,这里的this指向polygon对象本身,而非组件实例,也会引发属性访问错误。

修复步骤

1. 修复update方法的this指向

选择任意一种方案即可:

  • 方案A:requestAnimationFrame调用时用箭头函数包裹回调,保留组件实例的this指向
// ngOnInit 中原有调用改为
requestAnimationFrame(() => this.update());
// update 方法末尾的递归调用也同步修改
requestAnimationFrame(() => this.update());
  • 方案B:直接将update定义为箭头函数,从定义层面固定this指向
update = () => {
  // 原有update方法逻辑全部保留不变
}

2. 修正polygon内部的上下文访问

在定义polygon对象前先捕获组件实例的上下文,替换内部的this访问:

// ngOnInit 中定义poly前新增一行捕获组件实例
const component = this;
const poly = () => ({
  points: [],
  closed: false,
  addPoint(p) {
    this.points.push(point(p.x, p.y));
  },
  draw() {
    // 用捕获的component访问组件的context属性,不要用this
    const ctx = component.context;
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'red';
    ctx.fillStyle = 'rgba(255, 0, 0, 0.3)';
    ctx.beginPath();
    for (const p of this.points) {
      ctx.lineTo(p.x, p.y);
    }
    this.closed && ctx.closePath();
    ctx.stroke();
    this.closed && ctx.fill();
    // 后续draw方法内所有context访问都替换为ctx即可
    // drawLengthText、drawAngleText方法同理,都用component.context访问上下文
  },
  // 剩余的closest等方法逻辑无需修改
});

3. 可选优化(避免DOM未挂载异常)

当前你将canvas初始化逻辑写在ngOnInit中,此时@ViewChild查询的DOM元素还未完成挂载,建议将初始化逻辑挪到ngAfterViewInit生命周期钩子中,同时组件类实现AfterViewInit接口,避免偶发的canvas undefined问题。

内容的提问来源于stack exchange,提问作者Arter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 11:09:03