使用React 功能组件,我一直无法找到一种方法来使用异步接收的动态数据对我的图表进行动画处理。下面的沙盒说明了模拟异步读取的计时器的问题。
https://codesandbox.io/s/basic-column-chart-in-react-canvasjs-0gfv6?fontsize=14&hidenavigation=1&theme=dark
运行示例代码时,应会看到 5 个高度递增的垂直条以动画形式显示。 然后,在 5 秒后,它立即切换到 4 个下降高度的柱线。我希望该更新具有动画效果。
以下是我查看的一些参考信息: CanvasJS React 演示:其中许多在初始绘制时制作动画,但我找不到一个在初始渲染后加载动态数据进行动画处理的演示。
使用 JSON 数据的图表是一个演示,其中包含动态数据,但不进行动画处理。
回顾 CanvasJS 论坛,我发现了几个链接,但没有一个是针对 React 功能组件的
来自Team Canvas的Vishwas说:
要动态更新数据点并对图表进行动画处理,您可以实例化图表,通过图表选项更新数据点,然后调用 chart.render,如此更新的 JSFiddle 所示。
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "Animation test"
},
animationEnabled: true,
data: [{
type: "column",
dataPoints: []
}]
});
chart.options.data[0].dataPoints = [{ label: "Apple", y: 658 },
{ label: "Orange", y: 200 },
{ label: "Banana", y: 900 }];
chart.render();
此示例是纯 JS,但我试图使原理适应我的 React 功能组件。 为了更好地配合 React 最佳实践,我合并了用于存储数据的useState
钩子和用于处理获取的useEffect
钩子。但是,唉,我无法让我的沙盒使用动态数据进行动画处理。
我认为问题在于 CanvasJS 只希望在第一次渲染上制作动画,正如 Sanjoy 在 2016 年 7 月 19 日的 CanvasJS 论坛上所说。
我从 2015 年 1 月发现了这个 SO 问题,它表明:
我目前丑陋的解决方法是每次我都重新实例化图表 更新只是为了达到该动画效果。
我希望情况在过去四年中有所改善,但如果这个黑客仍然是最好/唯一的方法,我需要一些关于每次使用 React 功能组件重新实例化图表的指导。
要强制重新挂载组件,请在要重新挂载组件时传递不同的key
<CanvasJSChart
key={dataPoints.toString()} // force a remount when `dataPoints` change
containerProps={containerProps}
options={options}
onRef={ref => (chart.current = ref)}
/>
工作示例
这两个示例都可以正常工作。
您始终可以通过某种调用来为字符设置动画。在这种情况下,我使用setInterval。
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script>
var chart;
window.onload = function () {
chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "Animation test"
},
animationEnabled: true,
data: [{
type: "column",
dataPoints: []
}]
});
chart.options.data[0].dataPoints = [{ label: "Apple", y: 0 },
{ label: "Orange", y: 0 },
{ label: "Banana", y: 0 }];
chart.render();
}
var max = 0;
var s = {c: 0, i: 0};
function ANIMATE() {
if (typeof chart === 'undefined') return;
chart.options.data[0].dataPoints.forEach(function(item, index, array) {
if (index == s.i) {
array[index].y += 3;
s.c++;
}
if (s.c > 12) {
s.i++;
s.c = 0;
if (s.i == 15) { s.i = 0}
}
});
if (max < 12) {
chart.options.data[0].dataPoints.push({label: "apple" + Math.random(), y: 1 + Math.random() * 10});
max++;
}
chart.render()
}
setInterval(function(){
ANIMATE()
}, 1)
</script>
<div id="chartContainer" style="height: 370px; width: 100%;"></div>
我找到了部分答案。完全执行代码位于此代码沙箱中,但关键位是延迟图表的初始呈现,直到状态变量指示数据可用:
return (
<div className="App">
{!initialized ? (
<h1> Loading...</h1>
) : (
<CanvasJSChart containerProps={containerProps} options={options} />
)}
</div>
(;
这只是部分解决方案,因为后续数据更新仍然不会动画化。