1

我有一个很好的应用程序,它根据几个标准显示折线图。当主要标准发生变化时,我想清除当前的折线图。但是,我无法找到如何做到这一点。我正在使用 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);
    }
};

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

在主要标准的选择框中,我调用该函数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> 
4

2 回答 2

2

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

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

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

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

您可以尝试的第二种方法是使用 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 销毁函数来清除/销毁图表

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

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

编辑:

我找到了一种比修改库更好的新方法(我知道这不是一个好习惯,所以我试图找到这种新方法)

您仍然需要将 ChartJs 注入控制器

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

MyController.$inject = ['ChartJs'];

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

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

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(); 
            }
        }
    }
}

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

我希望它对我的英语有所帮助和抱歉

于 2015-05-27T01:05:28.723 回答
1

我想我找到了另一种对我更有效的方法,而且代码更少。

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>

于 2015-12-03T08:53:39.987 回答