4

我正在一个反应​​项目中绘制一个反应谷歌条形图(材料之一),我正在尝试制作动画。我读过这种图表不支持动画,但我需要这样做,必须有任何方法可以做到。我很难认为新事物比旧事物更糟糕。任何人都知道我该怎么做?我尝试了许多不同的方法,但没有任何效果。这是我的代码:

import React from 'react';
import './App.css';
import Chart from 'react-google-charts'

function App() {

  return (
    <div className="App">      
      <Chart
        width={'500px'}
        height={'300px'}
        // Note here we use Bar instead of BarChart to load the material design version
        chartType="Bar"
        loader={<div>Loading Chart</div>}
        data={[
          ['City', '2010 Population', '2000 Population'],
          ['New York City, NY', 8175000, 8008000],
          ['Los Angeles, CA', 3792000, 3694000],
          ['Chicago, IL', 2695000, 2896000],
          ['Houston, TX', 2099000, 1953000],
          ['Philadelphia, PA', 1526000, 1517000],
        ]}
        options={{
          // Material chart options
          chart: {
            title: 'Population of Largest U.S. Cities',
            subtitle: 'Based on most recent and previous census data',
          },
          hAxis: {
            title: 'Total Population',
            minValue: 0,
          },
          animation: {
            duration: 1000,
            easing: 'out',
            startup: true,
          },
          vAxis: {
            title: 'City',
          },
          bars: 'horizontal',
          axes: {
            y: {
              0: { side: 'right' },
            },
          },
        }}
      />
    </div>
  );
}

export default App;
4

3 回答 3

3

演示使用 react | 使用 vanilla javascript 演示

谷歌材料图表不支持动画。

如果您想为材料谷歌图表添加动画,您可以使用 css 动画手动完成。让我们这样做(演示):

首先我们应该得到一个实际柱的选择器。似乎第三个 svg 组(g标签)是图表中的实际条形图(其他组用于标签/标题/等):

.animated-chart g:nth-of-type(3) {...}

然后我们应该给它添加一个 css 过渡:

.animated-chart g:nth-of-type(3) {
  transition: 1s;
}

然后我们可以创建一个类 ( ) 用于在和.animated-chart-start之间切换,如下所示:transform: scaleX(1);transform: scaleX(0);

.animated-chart g:nth-of-type(3) {
  transition: 1s;
  transform: scaleX(1);
}
.animated-chart.animated-chart-start g:nth-of-type(3) {
  transform: scaleX(0);
}

到目前为止,我们添加了 css,现在我们应该将这些类添加到我们的图表中,并.animated-chart-start在短暂延迟后切换类。我们可以在 上做componentDidMount,但在准备好的图表上做会更干净:

<Chart
    ...
    className={`animated-chart animated-chart-start`}
    chartEvents={[
      {
        eventName: "ready",
        callback: ({ chartWrapper, google }) => {
          const chartEl = chartWrapper.getChart().container;
          setTimeout(() => {
            chartEl.classList.remove('animated-chart-start')
          }, 100)
        },
      }
    ]}
  />

它将.animated-chart-start类添加到图表中,并在 100 毫秒后将其删除。(100ms 是可选的,您也可以立即切换它)。

另请注意,谷歌图表似乎不支持将数据绑定到className(like className={this.state.dynamicClass}),这就是为什么我们不能使用状态变量来切换动画类。

最后,我们可以将这个动画图表包装到一个单独的组件AnimatedChart中,以使其更具可重用性。(你可以在 stackblitz 代码上看到它)。

实时运行

已知限制:

  • 在图表动画期间设置状态将导致重新渲染并破坏 css 转换。
  • 我们假设第三个 svg 组是图表。但它可能因图表类型甚至图表属性而异。

更新:对于垂直图表,您可以scaleY用于动画,并且您可能希望设置变换原点,例如:transform-origin: 0 calc(100% - 50px);使其看起来更好。(在 Stackblitz 上运行垂直版本

更新 2:对于 vanilla javascript 版本(没有任何框架),请参见此处

于 2020-09-01T11:16:37.543 回答
0

刚刚更新了代码并尝试以更好的方式重新实现它,但找不到更好的解决方案。

你需要和 CSS 一起玩一点

对于 Y 轴动画

g:nth-of-type(3) transition: 2s; transform: scaleX(1);

或者

对于 X 轴动画

g:nth-of-type(3) transform: scaleX(0);

https://codesandbox.io/s/google-react-chart-do602?file=/src/styles.css

于 2020-09-04T18:21:28.177 回答
0

您可以尝试通过在短时间内交换图表数据来模拟动画。这是我的建议分三步。

  1. 最初加载图表值为“0”的图表。
  2. 然后加载数据的部分值。
  3. 最后设置真实数据值。
function ChartBox() {

  let initialData = [
    ['City', '2010 Population', '2000 Population'],
    ['New York City, NY', 0, 0],
    ['Los Angeles, CA', 0, 0],
    ['Chicago, IL', 0, 0],
    ['Houston, TX', 0, 0],
    ['Philadelphia, PA', 0, 0],
  ];

  let n = 250; // divider
  let dataLoading = [
    ['City', '2010 Population', '2000 Population'],
    ['New York City, NY', 8175000/n, 8008000/n],
    ['Los Angeles, CA', 3792000/n, 3694000/n],
    ['Chicago, IL', 2695000/n, 2896000/n],
    ['Houston, TX', 2099000/n, 1953000/n],
    ['Philadelphia, PA', 1526000/n, 1517000/n],
  ];

  let finalData = [
    ['City', '2010 Population', '2000 Population'],
    ['New York City, NY', 8175000, 8008000],
    ['Los Angeles, CA', 3792000, 3694000],
    ['Chicago, IL', 2695000, 2896000],
    ['Houston, TX', 2099000, 1953000],
    ['Philadelphia, PA', 1526000, 1517000],
  ];

  const [chartData, setChartData] = useState(initialData);

  useEffect(() => {
    const timer = setTimeout(() => {
      setChartData(dataLoading)
    }, 100);
    const timer2 = setTimeout(() => {
      setChartData(finalData)
    }, 300);
    return () => {clearTimeout(timer); clearTimeout(timer2)}
  }, []);

  return (
    <div className="App">
      <Chart
        {...}
        data={chartData}
        {...}

使用 State Hook 和 useEffect 帮助操作我们想要呈现的数据。在<Chart/>组件中,我传递了chartData,该值将在 100 毫秒和 300 毫秒后发生变化。当然,您可以添加更多带有分数的步骤(如 dataLoading),因此您的“动画”看起来会更流畅。

于 2020-09-01T09:55:55.547 回答