charts-bar-chart.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import { loadFont } from "@remotion/google-fonts/Inter";
  2. import {
  3. AbsoluteFill,
  4. spring,
  5. useCurrentFrame,
  6. useVideoConfig,
  7. } from "remotion";
  8. const { fontFamily } = loadFont();
  9. const COLOR_BAR = "#D4AF37";
  10. const COLOR_TEXT = "#ffffff";
  11. const COLOR_MUTED = "#888888";
  12. const COLOR_BG = "#0a0a0a";
  13. const COLOR_AXIS = "#333333";
  14. // Ideal composition size: 1280x720
  15. const Title: React.FC<{ children: React.ReactNode }> = ({ children }) => (
  16. <div style={{ textAlign: "center", marginBottom: 40 }}>
  17. <div style={{ color: COLOR_TEXT, fontSize: 48, fontWeight: 600 }}>
  18. {children}
  19. </div>
  20. </div>
  21. );
  22. const YAxis: React.FC<{ steps: number[]; height: number }> = ({
  23. steps,
  24. height,
  25. }) => (
  26. <div
  27. style={{
  28. display: "flex",
  29. flexDirection: "column",
  30. justifyContent: "space-between",
  31. height,
  32. paddingRight: 16,
  33. }}
  34. >
  35. {steps
  36. .slice()
  37. .reverse()
  38. .map((step) => (
  39. <div
  40. key={step}
  41. style={{
  42. color: COLOR_MUTED,
  43. fontSize: 20,
  44. textAlign: "right",
  45. }}
  46. >
  47. {step.toLocaleString()}
  48. </div>
  49. ))}
  50. </div>
  51. );
  52. const Bar: React.FC<{
  53. height: number;
  54. progress: number;
  55. }> = ({ height, progress }) => (
  56. <div
  57. style={{
  58. flex: 1,
  59. display: "flex",
  60. flexDirection: "column",
  61. justifyContent: "flex-end",
  62. }}
  63. >
  64. <div
  65. style={{
  66. width: "100%",
  67. height,
  68. backgroundColor: COLOR_BAR,
  69. borderRadius: "8px 8px 0 0",
  70. opacity: progress,
  71. }}
  72. />
  73. </div>
  74. );
  75. const XAxis: React.FC<{
  76. children: React.ReactNode;
  77. labels: string[];
  78. height: number;
  79. }> = ({ children, labels, height }) => (
  80. <div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
  81. <div
  82. style={{
  83. display: "flex",
  84. alignItems: "flex-end",
  85. gap: 16,
  86. height,
  87. borderLeft: `2px solid ${COLOR_AXIS}`,
  88. borderBottom: `2px solid ${COLOR_AXIS}`,
  89. paddingLeft: 16,
  90. }}
  91. >
  92. {children}
  93. </div>
  94. <div
  95. style={{
  96. display: "flex",
  97. gap: 16,
  98. paddingLeft: 16,
  99. marginTop: 12,
  100. }}
  101. >
  102. {labels.map((label) => (
  103. <div
  104. key={label}
  105. style={{
  106. flex: 1,
  107. textAlign: "center",
  108. color: COLOR_MUTED,
  109. fontSize: 20,
  110. }}
  111. >
  112. {label}
  113. </div>
  114. ))}
  115. </div>
  116. </div>
  117. );
  118. export const MyAnimation = () => {
  119. const frame = useCurrentFrame();
  120. const { fps, height } = useVideoConfig();
  121. const data = [
  122. { month: "Jan", price: 2039 },
  123. { month: "Mar", price: 2160 },
  124. { month: "May", price: 2327 },
  125. { month: "Jul", price: 2426 },
  126. { month: "Sep", price: 2634 },
  127. { month: "Nov", price: 2672 },
  128. ];
  129. const minPrice = 2000;
  130. const maxPrice = 2800;
  131. const priceRange = maxPrice - minPrice;
  132. const chartHeight = height - 280;
  133. const yAxisSteps = [2000, 2400, 2800];
  134. return (
  135. <AbsoluteFill
  136. style={{
  137. backgroundColor: COLOR_BG,
  138. padding: 60,
  139. display: "flex",
  140. flexDirection: "column",
  141. fontFamily,
  142. }}
  143. >
  144. <Title>Gold Price 2024</Title>
  145. <div style={{ display: "flex", flex: 1 }}>
  146. <YAxis steps={yAxisSteps} height={chartHeight} />
  147. <XAxis height={chartHeight} labels={data.map((d) => d.month)}>
  148. {data.map((item, i) => {
  149. const progress = spring({
  150. frame: frame - i * 5 - 10,
  151. fps,
  152. config: { damping: 18, stiffness: 80 },
  153. });
  154. const barHeight =
  155. ((item.price - minPrice) / priceRange) * chartHeight * progress;
  156. return (
  157. <Bar key={item.month} height={barHeight} progress={progress} />
  158. );
  159. })}
  160. </XAxis>
  161. </div>
  162. </AbsoluteFill>
  163. );
  164. };