尝试在Bootstrap模式中动态生成图表,获取offsetWidth错误

时间:2015-04-09 04:02:22

标签: javascript canvas charts

我正在使用基于HTML5的库chartjs来动态绘制Bootstrap模式体内的图表。一切都很好,我可以看到已经传递了正确的数据和标签数组,并且已经创建了canvas HTML节点,但是我收到了这个错误:

Uncaught TypeError: Cannot read property 'offsetWidth' of undefined

我想也许我太早称这个功能了:

new Chart(--> HTML node <--).get(0).getContext("2d").Bar(--> data <--);

所以我把它放在setTimeout()块中以便在追加画布HTML节点2秒后调用该函数,但是我仍然收到该错误并且无法看到图表。

以下是完整的代码(githubDropbox),这是我调用图表库的部分:

document.getElementById("modalBody").appendChild(canvasElement);

setTimeout(function () {
    var ctx = document.getElementsByTagName("canvas")[0];
    var myNewChart = new Chart(ctx).get(0).getContext("2d").Bar(finalData);
    return finalData;
}, 2000);

1 个答案:

答案 0 :(得分:2)

我设法让这个工作在Plunkr

我为contextualizeForType2()contextualizeForType3()所做更改的基础知识如下:

  1. 实例化条形图组件的正确方法是使用附加的canvas元素的2D上下文。在代码中,new Chart(ctx.getContext('2d')).Bar(finalData);行后面有var ctx = ...。但是,由于尚未显示模态,因此它的高度和宽度均为0.
  2. 要使图表使用正确的高度和宽度,您应该绑定到模态完成动画后触发的shown.bs.modal事件。在该事件处理程序内部是您创建图表的位置。棘手的部分是因为你有两个不同的问题重用相同的模态。所以我添加了一个额外的.typeX命名空间,当模态被隐藏时,我会取消注册我的事件。
  3. 我知道第二点令人困惑,但希望代码清除它:

    var ctx = document.getElementsByTagName("canvas")[0];
    $('#myModal').on({
      'shown.bs.modal.type2': function() {
        new Chart(ctx.getContext("2d")).Bar(finalData);
      },
      'hidden.bs.modal.type2': function() {
        this.off('.type2');
      }
    });
    

    这意味着一旦模态被隐藏,当为另一种类型显示相同的模态时,这两个函数不会再次运行。此外,由于每次单击按钮时都添加了新的处理程序,因此您无法创建超出需要的图表。

    替代方法

    我有a further play并发现我可以将代码重构为一个可以从contextualizeForType2()contextualizeForType3()调用的函数,并传入finalData。这样做的好处是可以将所有画布和图表初始化代码保留在一个位置,从而简化了大型函数并使其更易于维护。

    功能是:

    function showModalChart(data) {
      var canvasElement = document.createElement("CANVAS");
      canvasElement.setAttribute("width", "400");
      canvasElement.setAttribute("height", "400");
    
      document.getElementById("modalBody").appendChild(canvasElement);
    
      var ctx = document.getElementsByTagName("canvas")[0];
      $('#myModal').off('.modalchart').on('shown.bs.modal.modalchart', function () {
          new Chart(ctx.getContext('2d')).Bar(data);
      });
    }