chart.js 加载全新数据
Posted
技术标签:
【中文标题】chart.js 加载全新数据【英文标题】:chart.js load totally new data 【发布时间】:2014-09-07 06:32:24 【问题描述】:The API for chart.js
允许编辑加载到其中的数据集的点,例如:
.update( )
在 Chart 实例上调用 update() 将重新渲染图表 任何更新的值,允许您编辑多个值 现有点,然后在一个动画渲染循环中渲染它们。
.addData( valuesArray, label )
在您的 Chart 实例上调用 addData(valuesArray, label) 传递一个 每个数据集的值数组,以及这些点的标签。
.removeData( )
在您的 Chart 实例上调用 removeData() 将删除第一个 图表上所有数据集的值。
所有这些都很棒,但我不知道如何加载一个全新的数据集,消除旧的。文档似乎没有涵盖这一点。
【问题讨论】:
【参考方案1】:我遇到了很大的问题
首先我尝试了.clear()
,然后我尝试了.destroy()
,我尝试将我的图表引用设置为null
最终解决了我的问题:删除 <canvas>
元素,然后将新的 <canvas>
重新附加到父容器
有一百万种方法可以做到这一点:
var resetCanvas = function ()
$('#results-graph').remove(); // this is my <canvas> element
$('#graph-container').append('<canvas id="results-graph"><canvas>');
canvas = document.querySelector('#results-graph'); // why use jQuery?
ctx = canvas.getContext('2d');
ctx.canvas.width = $('#graph').width(); // resize to parent width
ctx.canvas.height = $('#graph').height(); // resize to parent height
var x = canvas.width/2;
var y = canvas.height/2;
ctx.font = '10pt Verdana';
ctx.textAlign = 'center';
ctx.fillText('This text is centered on the canvas', x, y);
;
【讨论】:
这个答案有效,但我发现 destroy 在最新版本中也有效。在这篇文章中推荐 - github.com/nnnick/Chart.js/issues/559 这将有助于清空图形容器 div 以删除旧的 iframe $('#results-graph').remove(); $('#graph-container').empty(); $('#graph-container').append('【参考方案2】:你需要销毁:
myLineChart.destroy();
然后重新初始化图表:
var ctx = document.getElementById("myChartLine").getContext("2d");
myLineChart = new Chart(ctx).Line(data, options);
【讨论】:
就这样使用 if(window.myLine) window.myLine.destroy(); OR if(myLineChart) myLineChart.destroy(); 可以确认销毁然后重新初始化不会导致任何闪烁,并且看起来数据点是动态更新的【参考方案3】:使用 Chart.js V2.0,您可以执行以下操作:
websiteChart.config.data = some_new_data;
websiteChart.update();
【讨论】:
正是操作所要求的。 当我做chart.config.data = newData
时,我有这个错误:TypeError: undefined is not an object (evaluating 'i.data.datasets.length')
有人有同样的问题吗?【参考方案4】:
这是一个旧线程,但在当前版本中(截至 2017 年 2 月 1 日),很容易替换在 chart.js 上绘制的数据集:
假设您的新 x 轴值在数组 x 中,y 轴值在数组 y 中, 您可以使用下面的代码来更新图表。
var x = [1,2,3];
var y = [1,1,1];
chart.data.datasets[0].data = y;
chart.data.labels = x;
chart.update();
【讨论】:
非常感谢,伙计!浪费了一整天。终于偶然发现了你的答案。谢谢。 这对我很有帮助。即使只是使用 [] 设置一个空数据集,然后执行新的“推送”也可以达到目的。【参考方案5】:ChartJS 2.6 支持数据引用替换(请参阅 update(config) 文档中的Note)。所以当你有你的图表时,你基本上可以这样做:
myChart.data.labels = ['1am', '2am', '3am', '4am'];
myChart.data.datasets[0].data = [0, 12, 35, 36];
myChart.update();
它不会执行您通过添加点获得的动画,但图表上的现有点将被动画化。
【讨论】:
【参考方案6】:我对此的解决方案非常简单。 (版本 1.X)
getDataSet:function(valuesArr1,valuesArr2)
var dataset = [];
var arr1 =
label: " (myvalues1)",
fillColor: "rgba(0, 138, 212,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(0, 138, 212,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data: valuesArr1
;
var arr2 =
label: " (myvalues2)",
fillColor: "rgba(255, 174, 087,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(255, 174, 087,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data: valuesArr2
;
/*Example conditions*/
if(condition 1)
dataset.push(arr1);
if(condition 2)
dataset.push(arr1);
dataset.push(arr2);
return dataset;
var data =
labels: mylabelone,
datasets: getDataSet()
;
if(myBarChart != null) // i initialize myBarChart var with null
myBarChart.destroy(); // if not null call destroy
myBarChart = new Chart(ctxmini).Bar(data, options);//render it again ...
没有闪烁或问题。 getDataSet
是一个控制我需要呈现什么数据集的函数
【讨论】:
能不能把getDataSet()的sn-p代码也加进去? 添加了 getDataSet() 示例【参考方案7】:我在这里回答了这个问题,请参阅How to clear a chart from a canvas so that hover events cannot be triggered?
但这里是解决方案:
var myPieChart=null;
function drawChart(objChart,data)
if(myPieChart!=null)
myPieChart.destroy();
// Get the context of the canvas element we want to select
var ctx = objChart.getContext("2d");
myPieChart = new Chart(ctx).Pie(data, animateScale: true);
【讨论】:
【参考方案8】:根据文档,clear()
清除画布。将其视为 Paint 中的橡皮擦工具。它与图表实例中当前加载的数据无关。
销毁实例并创建一个新实例是浪费。相反,请使用 API 方法 removeData()
和 addData()
。这些将在图表实例中添加/删除单个段。所以如果你想加载全新的数据,只需循环一个图表数据数组,然后调用removeData(index)
(数组索引应该对应于当前段索引)。然后,使用addData(index)
用新数据填充它。我建议包装这两种循环数据的方法,因为它们期望单个段索引。我使用resetChart
和updateChart
。 在继续之前,请务必查看 Chart.js
最新版本和文档。他们可能已经添加了完全替换数据的新方法。
【讨论】:
我喜欢你的回答,它与我在网上阅读的信息一致。如果您能够展示和举例,那将非常有帮助。我在网上看到的两个类似的例子是:jsbin.com/yitep/5/edit?html,js,output和jsbin.com/yitep/4/edit?html,js,output 唯一的问题是,如果您必须用本质上完全不同的数据集替换图表数据,更新图表会变得非常麻烦且超级慢。对于初学者,我还没有找到更新现有 x 轴 标签 的方法。在这种情况下,销毁并重新实例化整个图表是唯一真正的解决方案。 不幸的是,我只处理了一个不太复杂的甜甜圈图。您是否查看了最新的 API?【参考方案9】:我遇到了同样的问题,我在一个页面上有 6 个饼图,可以同时更新。我正在使用以下函数来重置图表数据。
// sets chart segment data for previously rendered charts
function _resetChartData(chart, new_segments)
// remove all the segments
while (chart.segments.length)
chart.removeData();
;
// add the new data fresh
new_segments.forEach (function (segment, index)
chart.addData(segment, index);
);
;
// when I want to reset my data I call
_resetChartData(some_chart, new_data_segments);
some_chart.update();
【讨论】:
虽然这可行,但我发现与完全重新创建图表相比,它慢得多(由于添加每个点时的动画)。【参考方案10】:不必破坏图表。试试这个
function removeData(chart)
let total = chart.data.labels.length;
while (total >= 0)
chart.data.labels.pop();
chart.data.datasets[0].data.pop();
total--;
chart.update();
【讨论】:
【参考方案11】:我尝试了neaumusic的解决方案,但后来发现only problem with destroy is the scope。
var chart;
function renderGraph()
// Destroy old graph
if (chart)
chart.destroy();
// Render chart
chart = new Chart(
document.getElementById(idChartMainWrapperCanvas),
chartOptions
);
将我的图表变量移到函数范围之外,让它为我工作。
【讨论】:
【参考方案12】:以上答案都没有以非常简洁的方式以最少的代码帮助我的特殊情况。我需要删除所有数据集,然后循环以动态添加几个数据集。所以这个片段是为那些一直到页面底部而没有找到答案的人准备的:)
注意:确保在将所有新数据加载到数据集对象后调用 chart.update()。希望这可以帮助某人
function removeData(chart)
chart.data.datasets.length = 0;
function addData(chart, data)
chart.data.datasets.push(data);
【讨论】:
【参考方案13】:您需要清理旧数据。无需重新初始化:
for (i in myChartLine.datasets[0].points)
myChartLine.removeData();
【讨论】:
【参考方案14】:请了解 Chart.js(此处为第 2 版)的工作原理,并针对您想要的任何属性进行操作:
1.请假设您的 HTML 中有如下条形图:
<canvas id="your-chart-id" ></canvas>
2.请假设您有一个第一次填充图表的 javascript 代码(例如在加载页面时):
var ctx = document.getElementById('your-chart-id').getContext('2d');
var chartInstance = new Chart(ctx,
type: 'bar',
data:
labels: your-lables-array,
datasets: [
data: your-data-array,
/*you can create random colors dynamically by ColorHash library [https://github.com/zenozeng/color-hash]*/
backgroundColor: your-lables-array.map(function (item)
return colorHash.hex(item);
)
]
,
options:
maintainAspectRatio: false,
scales:
yAxes: [ ticks: beginAtZero: true ]
,
title: display: true, fontSize: 16, text: 'chart title',
legend: display: false
);
请假设您想要完全更新您的数据集。 这很简单。请查看上面的代码,看看从图表变量到数据的路径如何,然后按照以下路径:
选择chartInstance
var.
然后在chartInstance
中选择data node
。
然后在data node
中选择datasets node
。(注意:As
你可以看到,datasets node
是一个数组。所以你必须
指定你想要的这个数组的哪个元素。这里我们只有一个
datasets node
中的元素。所以我们使用datasets[0]
所以选择datasets[0]
然后在datasets[0]
里面选择data node
。
此步骤为您提供chartInstance.data.datasets[0].data
,您可以设置新数据并更新图表:
chartInstance.data.datasets[0].data = NEW-your-data-array
//finally update chart var:
chartInstance.update();
注意: 按照上面的算法,你可以简单的实现到你想要的每个节点。
【讨论】:
【参考方案15】:如果有人正在寻找如何在 React 中执行此操作。对于折线图,假设您在图表周围有一个包装器组件:
(假设您使用的是 v2。您不需要使用 react-chartjs
。这是使用来自 npm 的普通 chart.js
包。)
propTypes:
data: React.PropTypes.shape(
datasets: React.PropTypes.arrayOf(
React.PropTypes.shape(
)
),
labels: React.PropTypes.array.isRequired
).isRequired
,
componentDidMount ()
let chartCanvas = this.refs.chart;
let myChart = new Chart(chartCanvas,
type: 'line',
data: this.props.data,
options:
...
);
this.setState(chart: myChart);
,
componentDidUpdate ()
let chart = this.state.chart;
let data = this.props.data;
data.datasets.forEach((dataset, i) => chart.data.datasets[i].data = dataset.data);
chart.data.labels = data.labels;
chart.update();
,
render ()
return (
<canvas ref='chart' height='400' width='600'></canvas>
);
componentDidUpdate
功能允许您更新、添加或删除this.props.data
中的任何数据。
【讨论】:
【参考方案16】:到目前为止,我能为自己找到的唯一解决方案是从头开始重新初始化图表:
var myLineChart = new Chart(ctx).Line(data, options);
然而,这对我来说似乎有点做作。任何人有更好、更标准的解决方案吗?
【讨论】:
这对我来说非常有用,除了你需要先做 myLineChart.destroy() 来摆脱旧的,否则你会在重绘时闪烁。【参考方案17】:我也遇到了很多麻烦。我在单独的数组中有数据和标签,然后我重新初始化图表数据。我添加了 line.destroy();如上所述,这已经成功了
var ctx = document.getElementById("canvas").getContext("2d");
if(window.myLine)
window.myLine.destroy();
window.myLine = new Chart(ctx).Line(lineChartData,
etc
etc
【讨论】:
【参考方案18】:有一种方法可以在不清除画布或重新开始的情况下执行此操作,但您必须手动处理图表的创建,以便更新时数据的格式相同。
这是我的做法。
var ctx = document.getElementById("myChart").getContext("2d");
if (chartExists)
for (i=0;i<10;i++)
myNewChart.scale.xLabels[i]=dbLabels[i];
myNewChart.datasets[0].bars[i].value=dbOnAir[i];
myNewChart.update();
else
console.log('chart doesnt exist');
myNewChart = new Chart(ctx).Bar(dataNew);
myNewChart.removeData();
for (i=0;i<10;i++)
myNewChart.addData([10],dbLabels[i]);
for (i=0;i<10;i++)
myNewChart.datasets[0].bars[i].value=dbOnAir[i];
myNewChart.update();
chartExists=true;
我基本上将创建时加载的数据废弃,然后用添加数据方法进行改造。这意味着我可以访问所有点。每当我尝试访问由以下创建的数据结构时:
Chart(ctx).Bar(dataNew);
命令,我无法访问我需要的内容。这意味着您可以按照创建它们的相同方式更改所有数据点,并且还可以调用 update() 而无需完全从头开始制作动画。
【讨论】:
【参考方案19】:图表 JS 2.0
刚刚设置 chart.data.labels = [];
例如:
function addData(chart, label, data)
chart.data.labels.push(label);
chart.data.datasets.forEach((dataset) =>
dataset.data.push(data);
);
chart.update();
$chart.data.labels = [];
$.each(res.grouped, function(i,o)
addData($chart, o.age, o.count);
);
$chart.update();
【讨论】:
【参考方案20】:创建图表对象时,您需要将实例保存在变量中。
var currentChart = new Chart(ctx, ...);
在加载新数据之前,您需要销毁它:
currentChart.destroy();
【讨论】:
【参考方案21】:首先,让变量记住图表的一个实例。
let yourChart = new Chart(ctxBar,
type: 'bar',
data:
labels: labels,
datasets: datasets
,
);
其次,我最苦恼的事情是在更新图表之前以正确的格式获取数据结构。所以看了图表js对象的data
键结构后:
data:
labels: ['Jan', 'Feb'],
datasets: [
label: 'Net sales',
data: data
,
label: 'Cost of goods sold',
data: data
,
label: 'Gross margin',
data: data
]
请注意,data
键值是一个由两个键组成的对象,labels
和 datasets
。 labels
key'的值是一个数组,而datasets
key'的值也是一个以对象为值的数组。
因此,我使用的图表实例中的remove
标签和数据集:
yourChart.data.labels = [];
yourChart.data.datasets = [];
yourChart.update();
到add
标签和数据集到我使用的图表实例:
yourChart.data.labels = ['label 1', 'label 2'];
yourChart.data.datasets = [
label: 'column lables',
data: [450, 50],
backgroundColor: ["#dc3545", "#ffb759"]
];
yourChart.update();
准备服务器端 标签和数据集值可以在服务器端按如下方式准备(在我的情况下为 php):
$datajs = function ($data, $bg_colour) // function emulating chart js datasets key value structure
return [
'data' => $data,
'backgroundColor' => $bg_colour
];
;
$datasets = [];
$labels = ['label 1', 'label 2'];
$datasets[] = $datajs([42,10], ["#dc3545", "#ffb759"]);
$datasets[] = $datajs([100,5], ["#dc3545", "#ffb759"]);
仅从数据集中的数据键值替换数据(我没有测试过)
yourChart.data.datasets.forEach((dataset) =>
dataset.data = [];
);
yourChart.update();
// if you have an array of arrays
let array = [[42,20],[58,68],[78,1]];
let length = yourChart.data.datasets.length;
for (let i = 0; i < array.length; i++)
const element = array[i];
if (i < length)
yourChart.data.datasets[i].data = element;
else
yourChart.data.datasets[] = data: element;
yourChart.update();
【讨论】:
以上是关于chart.js 加载全新数据的主要内容,如果未能解决你的问题,请参考以下文章
使用require.js发出加载chart.js缩放插件的问题