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

Angular同页面多Chart.js图表修改Rectangle.prototype.draw互相干扰如何解决

问题根源

你直接修改了Chart.js的全局原型方法,所有图表实例都会共用这个修改后的逻辑,自然会互相影响。你在方法外部判断DOM是否存在的逻辑仅在执行customizeChartJs时生效,一旦原型被覆盖,之后所有图表的矩形绘制都会走你修改后的代码,和外部判断无关。

解决方案

通过保留原生方法+图表配置加专属标识+draw方法内分支判断的方式隔离不同图表的绘制逻辑,具体修改如下:

1. 先保存原生draw方法,避免覆盖后无法恢复

// 全局只执行一次,保存原生矩形绘制逻辑
const originalRectangleDraw = Chart.elements.Rectangle.prototype.draw;

2. 给自定义图表加专属标识

在初始化CustomerRetention类型图表时,给配置项加唯一标记:

const retentionChartConfig = {
  type: 'CustomerRetention',
  options: {
    // 加专属标识,用于draw方法内判断
    isRetentionChart: true,
    // 其余原有配置保持不变
  }
}

3. 修改自定义draw逻辑,增加分支判断

private customizeChartJs() {
  // 加标记避免重复覆盖原型
  if (Chart.elements.Rectangle.prototype.draw._customized) return;

  try {
    Chart.elements.Rectangle.prototype.draw = function () {
      // 仅处理带专属标识的留存图表
      if (this._chart.config.options.isRetentionChart) {
        // 这里放你原来的所有自定义绘制逻辑
        const ctx = this._chart.ctx;
        const vm = this._view;
        let left, right, top, bottom, signX, signY, borderSkipped;
        // ... 其余原有绘制代码完全保留
      } else {
        // 其他图表走原生绘制逻辑
        originalRectangleDraw.apply(this, arguments);
      }
    };
    // 打标记避免重复覆盖
    Chart.elements.Rectangle.prototype.draw._customized = true;

    // 原有自定义控制器、tooltip逻辑完全保留即可,你已经注册了专属的CustomerRetention类型,不会影响其他图表
    Chart.defaults.CustomerRetention = Chart.defaults.bar;
    Chart.Tooltip.positioners.custom = (elements, position) => {
      // 原有tooltip逻辑不变
    };
    Chart.controllers.CustomerRetention = Chart.controllers.bar.extend({
      // 原有控制器逻辑不变
    });
  } catch (e) {
    console.error(e);
  }
}

额外说明

如果另一个图表也需要自定义绘制逻辑,只需要给它加另一个专属标识,在draw方法中新增对应处理分支即可,两个图表的绘制逻辑完全隔离不会互相干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 17:39:02