如何清除 angular-图表的数据

How to clear the data for a angular-chart

我有一个很好的应用程序,可以显示基于多个条件的折线图。当主要标准发生变化时,我想清除当前的折线图。但是,我无法找到如何执行此操作。我正在使用 AngulerJS v1.4.0-rc2、Chart.js v1.0.2 和 angular-chart v0.7.1.

加载页面时,我调用函数 updateSelection()。当任何其他条件发生变化时,也会调用此函数。函数实现为:

$scope.updateSelection = function() {
    $scope.chartLabels = maandData;
    if ($scope.isPostcodeArea()) {
        $scope.chartSeries = getPostcodeSeries();
        $scope.chartData = getPostcodeData($scope.dataArea.index, $scope.dataMetric.index);
    } else {
        $scope.chartSeries = getSelectionSeries();
        $scope.chartData = getSelectionData($scope.dataArea.index, $scope.dataMetric.index);
    }
};

这将根据主要条件调用适当的函数来初始化折线图的数据。在网页中显示数据条目显示正确的值。

在主要标准的 select 框中,我调用函数 updateArea():

$scope.updateArea = function() {
    $scope.form.$setPristine();
    if ($scope.isPostcodeArea()) {
        $scope.postcodeSelection = null;
        $scope.postcodeCompare1 = null;
        $scope.postcodeCompare2 = null;
        $scope.postcodeCompare3 = null;
    } else {
        $scope.selectionData = null;
        $scope.selectionCompare1 = null;
        $scope.selectionCompare2 = null;
        $scope.selectionCompare3 = null;
    }
    $scope.selections = getSelections($scope.dataArea.index);
    $scope.selectionLabel = $scope.areas[$scope.dataArea.index].label;
    $scope.chartLabels = [];
    $scope.chartSeries = [];
    $scope.chartData = [];
};

此函数将重置输入表单和表单数据。它还将确定另一个标准 (selections) 的数据,一个适合该标准的标签 (selectionLabel),并且它应该重置图表数据。

但是,图表不会更新以反映新数据。那么,有没有办法正确重置数据?

图表本身使用以下 HTML 显示:

<canvas id="line" class="chart chart-line"
    data="chartData" labels="chartLabels" series="chartSeries"
    legend="true" options="{'scaleBeginAtZero': true, 'datasetFill': false}">
</canvas> 

我遇到了同样的问题,找到了两种解决方法

第一种方法是获取 canvas 的上下文并使用 clearRect 函数:

var canvas = document.getElementById('line');
if (canvas){
    var ctx = canvas.getContext('2d');
    ctx.clearRect(0,0, ctx.canvas.width, ctx.canvas.height);
}

这样你就可以清除 canvas,不管你的数据是否仍然设置。这样做我遇到了悬停事件的问题,当我将鼠标移到它上面时,canvas 再次设置了数据。所以我寻找另一种方法来做到这一点。

您可以尝试的第二种方法是使用 ChartJsProvider:

1.- 在 angular-chart.js 文件的 createChart 函数中,在变量图表初始化之后添加此行:

var chart = new ChartJs.Chart(ctx)[type](data, options);
ChartJs.createdChart = chart; // add this line so you can access chart variable from ChartJsProvider

2.- 将 ChartJs 注入控制器

angular.module('myModule')
    .controller('MyController', MyController);

MyController.$inject = ['ChartJs'];

function MyController(ChartJs){
    // your controller code
}

3.- 在您的控制器中使用 createdChart destroy 函数 clear/destroy 图表

var canvas = document.getElementById('line');
if (canvas) { 
    ChartJs.createdChart.destroy();
}

这种方式在 chrome、歌剧和 safari 中对我来说是正确的。

已编辑:

我找到了一种比修改库更好的新方法(我知道这不是一个好的做法,所以这就是我尝试寻找这种新方法的原因)

你还需要给Controller注入ChartJs

angular.module('myModule')
    .controller('MyController', MyController);

MyController.$inject = ['ChartJs'];

function MyController(ChartJs){
    // your controller code
}

我使用参数 elementId 创建了一个名为 clearChart 的函数,因此如果您的页面中有多个图表,您可以直接访问您想要的图表 clear/remove:

function clearChart(elementId) {
    if (document.getElementById(elementId)) {
        var charts = ChartJs.Chart.instances; // Get all chart instances
        for (var key in charts){ // loop looking for the chart you want to remove
            if (!charts.hasOwnProperty(key)){
                continue;
            }
            var chartAux = ChartJs.Chart.instances[key]; 
            if (chartAux.chart.ctx.canvas.id === elementId){ 
                // Remove chart-legend before destroying the chart
                var parent = chartAux.chart.ctx.canvas.parentElement;
                var legend = chartAux.chart.ctx.canvas.nextElementSibling;
                parent.removeChild(legend);
                // Compare id with elementId passed by and if it is the one            
                // you want to remove just call the destroy function
                ChartJs.Chart.instances[key].destroy(); 
            }
        }
    }
}

这个新的第二种方式非常适合我。

希望对我有所帮助,抱歉我的英语不好

我想我找到了另一种更适合我的方法,而且它用更少的代码完成。

Chart.js 正在发出一个 onCreate 事件,您正在获取创建的图表对象。

然后我将该对象存储在一个变量中,以便我可以在我的点击处理程序中使用它。 (如果您的页面上有多个图表,您可能会收到多个 onCreate 事件,并且您可以将每个图表对象存储在一个数组或对象中供以后使用。)

在点击处理程序中,您可以调用 lineChart.destroy(),这将破坏您的图表对象。也不要忘记清除您的数据。如果您再次需要,图表将由 angular-chartjs 重新创建。

这样做的好处是一切都被重置了。我之前遇到过其他方法没有清除x轴刻度的问题。

请查看下面或此 jsfiddle 中的演示。

我需要在我的演示中检查的一个问题是图表在每个新数据时都完全重新生成。也许这是正常行为,但我不确定。

angular.module('chartDemo', ['chart.js'])
 .config(['ChartJsProvider', function (ChartJsProvider) {
    // Configure all charts
    ChartJsProvider.setOptions({
      animation: false,
      colours: ['#FF5252', '#FF8A80'],
      //responsive: false
    });
    // Configure all line charts
    ChartJsProvider.setOptions('Line', {
      //datasetFill: false
      //legendTemplate: /*'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><button ng-click="mainCtrl.toggle()">test</button><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'*/
    });
  }])
 .controller('MainController', MainController);

function MainController($scope, $timeout) {
  var vm = this;
  var defaultData = [
      [65, 59, 80, 81, 56, 55, 40]
   ],
    lineChart; //created in onCreate
  
  angular.extend(vm, {
   series: ['Series A'], 
   data: defaultData,
    labels: Object.keys(defaultData[0]),
   onClick: function (points, evt) {
     console.log(points, evt);
   },
    enable: true,
    onChange: function() {
      if ( vm.enable )
       startTimer();
    },
    clear: function() {
      console.log('clear chart');
      vm.data = [[]];
      lineChart.destroy();
    },
    startTimer: startTimer,
    toggle: function() {
      consoel.log('Test')
    }
  });
 
  $scope.toggle = function() {
    // not working yet
    console.log('test');
  };
  
  $scope.$on('toggle', function(e, data) {
    console.log(data);
  });
  
  //console.log(Object.keys(defaultData[0]));
  
  function startTimer() {
    if ( vm.enable ) {
     $timeout(function() {
          vm.data[0].push(Math.random()*50);
          startTimer();
          vm.labels = Object.keys(vm.data[0])
       }, 500);
    }
  }
  
  if (vm.enable) startTimer();
  
  $scope.$on('create', function (event, chart) {
   console.log(chart);
    lineChart = chart;
 });
}

MainController.$inject = ['$scope', '$timeout'];
<link href="https://cdn.rawgit.com/jtblin/angular-chart.js/master/dist/angular-chart.css" rel="stylesheet"/>
<script src="https://cdn.rawgit.com/alanszp/Chart.js/master/Chart.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdn.rawgit.com/jtblin/angular-chart.js/master/dist/angular-chart.min.js"></script>


<div ng-app="chartDemo" ng-controller="MainController as mainCtrl">
  enable<input type="checkbox" ng-model="mainCtrl.enable" ng-change="mainCtrl.startTimer();"/><button ng-click="mainCtrl.clear()">Clear</button>
    <canvas id="line" 
      class="chart chart-line" chart-data="mainCtrl.data" 
      chart-labels="mainCtrl.labels" 
      chart-legend="true" chart-series="mainCtrl.series" chart-legend="true"
      chart-click="mainCtrl.onClick"></canvas> 
  <pre>{{mainCtrl.debug}}</pre>
</div>