BarWithAnimation.tsx 1.48 KB
Newer Older
Yoon, Daeki's avatar
Yoon, Daeki committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { ScaleBand, ScaleLinear } from "d3-scale";
import React, { Fragment, useEffect, useRef } from "react";

type Props = {
  dataset: number[];
  height: number;
  xScale: ScaleBand<number>;
  yScale: ScaleLinear<number, number>;
};

export const BarWithAnimation = ({
  dataset,
  height,
  xScale,
  yScale,
}: Props) => {
  // console.log("dataset:", dataset);
  const preDataset = useRef(dataset);
  useEffect(() => {
    preDataset.current = dataset;
  }, [dataset]);

  const getStyle = (i: number) => {
    const style = {
      // fill: "red",
      animationName: `inmoveleftright-${i}`,
      animationDuration: "1s",
      // animationDirection: "alternate",
      animationIterationCount: "1",
      // transformOrigin: "bottom",
    };
    return style;
  };

  return (
    <g transform={`scale(1, -1) translate(0, ${-height})`}>
      {dataset.map((d, i) => {
        // console.log("d", d, "i", i, "x:", xScale(i), "y", yScale(d));
        return (
          <Fragment key={Math.random()}>
            <style>
              {`
@keyframes inmoveleftright-${i} {
  0% {
    height: ${yScale(preDataset.current[i])}px;
  }
  100% {
    height: ${yScale(d)}px;
  }
}  
`}
            </style>
            <rect
              x={xScale(i)}
              y={0}
              width={xScale.bandwidth()}
              height={yScale(d)}
              fill={`rgb(0, 0, ${Math.round(d * 10)})`}
              style={getStyle(i)}
            ></rect>
          </Fragment>
        );
      })}
    </g>
  );
};