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
相关产品推荐
相关产品推荐

