首页 文章

在Angular-chart.js中动态创建的画布上创建图表

提问于
浏览
1

我有一个div需要托管图表或表格,具体取决于XHR响应 . 在图表的情况下,我需要将div内容替换为chart.js用于显示图形的canvas元素 .

如果我将canvas元素添加到HTML代码中,angular-chart.js会呈现图形 . 但是,如果我使用javascript将画布注入div,则canvas元素将位于dom中,但不会显示图表 .

我该如何解决这个问题?

HTML

<div ng-controller="ChartCtrl">
  <div>
    {{chart.name}}
    This works (doughnut):
    <canvas id="chart-{{$index}}" class="chart chart-doughnut" chart-data="chart.data" chart-labels="chart.labels"></canvas>
  </div>
  This Doesn't work ({{chart.type}}):
  <div id="chartDiv"> </div>
</div>

Javascript

var myApp = angular.module('myApp', ['chart.js']);

// Create the controller, the 'ToddlerCtrl' parameter 
// must match an ng-controller directive
myApp.controller('ChartCtrl', function ($scope) {
   var chart_div = $('#chartDiv');
   chart_div.empty();
   canvas_html = '<canvas id="chart-2" class="chart chart-doughnut" chart-data="chart.data" chart-labels="chart.labels"></canvas>';
   console.log(canvas_html)
   chart_div.append(canvas_html);
   //console.log(chart_div)
  $scope.chart =    {
     name: 'Chart 1',
     type: 'Doughnut',
     labels: ['EVSC', 'ISB'],
     data: [13, 44]
   };
});

Plunker示例:http://plnkr.co/edit/9JkANojIl8EXRj3hJNVH?p=preview

2 回答

  • 1

    你正在改变DOM的结构,你不能以“vanilla”或“jQuery”方式附加你新创建的元素 .

    您需要将HTML字符串或DOM元素compile放入模板中,以生成将链接到 scope 的模板函数 . 该过程将遍历DOM树并将DOM元素与directives匹配 .

    // Instantiate the app, the 'myApp' parameter must match what is in ng-app
    var myApp = angular.module('myApp', ['chart.js']);
    
    // Create the controller, the 'ToddlerCtrl' parameter must match an ng-controller directive
    myApp.controller('ChartCtrl', function ($scope, $compile) {
      canvas_html = '<canvas id="chart-2" class="chart chart-doughnut" chart-data="chart.data" chart-labels="chart.labels"></canvas>';
    
      var element = angular.element(canvas_html);
      $compile(element)($scope);
      angular.element('#chartDiv').append(element);
    
      $scope.chart =    {
         name: 'Chart 1',
         type: 'Doughnut',
         labels: ['EVSC', 'ISB'],
         data: [13, 44]
       };
    });
    

    你可以在this Plunker example查看结果 .

  • 1

    @ HiDeo的答案是现货,但这是一个简化的指令来做同样的事情(注意 $compile 仍然) . 附加到 scopechartData 变量是Chartjs图表的预设,任何都可以工作 - 唯一需要注意的是我已经添加到 update 属性的 $watch :如果你要更新你的图表我会建议做某事这样只是为了保持双手清洁 .

    .directive('replaceWithChart',function($compile){
        return {
            restrict: 'A',
            scope: {
                chartData: '=replaceWithChart',
                height: '=',
                width: '='
            },
            compile: function(element){
                var canvasModel = angular.element('<canvas></canvas>');
                return {
                    post: function postLink(scope,elem,attr){
                        elem.empty();
                        var canvas = canvasModel.clone();
                        elem.append($compile(canvas)(scope));
    
                        !scope.height && (scope.height = elem[0].style.height || (elem[0].offsetHeight || elem[0].clientHeight));
                        !scope.width && (scope.width = elem[0].style.width || (elem[0].offsetWidth || elem[0].clientWidth));
    
                        var chart = new Chart(canvas[0].getContext('2d'),scope.chartData);
                        canvas.attr('height',(canvas[0].style.height = scope.height + 'px'));
                        canvas.attr('width',(canvas[0].style.width = scope.width + 'px'));
    
                        scope.$watch('chartData.update',function(){
                            scope.chartData.update && !(scope.chartData.update = false) && chart.update();
                        });
                        elem.on('$destroy',chart.destroy.bind(chart));
                        // Fixed some rendering issue, but I can't remember which
                        window.setTimeout(function(){
                            var padding = elem[0].style.padding || (window.getComputedStyle(elem[0],null).getPropertyValue('padding'));
                            elem[0].style.padding = '0';
                            elem[0].style.padding = padding;
                            chart.resize();
                        },300); // Magic number - I found this worked best
                    }
                };
            }
        };
    })
    

相关问题