App.js 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import React from 'react';
  2. import StockHeatmap from '@rongmz/react-stock-heatmap';
  3. import '@rongmz/react-stock-heatmap/dist/index.css';
  4. export default () => {
  5. const [loading, setLoading] = React.useState(true);
  6. const progressRef = React.useRef(null);
  7. /** @type {React.MutableRefObject<StockHeatmap>} */
  8. const heatmapRef = React.useRef(null);
  9. const [windowDim, setWindowDim] = React.useState([0, 0]);
  10. // ------------ Load data -------------
  11. React.useEffect(() => {
  12. setLoading(true);
  13. fetch('20200814').then(async ({ body, headers }) => {
  14. const reader = body.getReader();
  15. // Step 2: get total length
  16. const contentLength = +headers.get('Content-Length');
  17. // Step 3: read the data
  18. let receivedLength = 0; // received that many bytes at the moment
  19. let chunks = []; // array of received binary chunks (comprises the body)
  20. while (true) {
  21. const { done, value } = await reader.read();
  22. if (done) {
  23. break;
  24. }
  25. chunks.push(value);
  26. receivedLength += value.length;
  27. // console.log(`Received ${receivedLength} of ${contentLength} %=${100 * (receivedLength / contentLength)}`)
  28. if (progressRef.current !== null) {
  29. progressRef.current.innerHTML = ` Downloading ${(100 * receivedLength / contentLength).toFixed(1)}% ...`
  30. }
  31. }
  32. // Step 4: concatenate chunks into single Uint8Array
  33. let chunksAll = new Uint8Array(receivedLength); // (4.1)
  34. let position = 0;
  35. for (let chunk of chunks) {
  36. chunksAll.set(chunk, position); // (4.2)
  37. position += chunk.length;
  38. }
  39. // Step 5: decode into a string
  40. let result = new TextDecoder("utf-8").decode(chunksAll);
  41. // setdata
  42. if (heatmapRef.current !== null) {
  43. heatmapRef.current.setData(
  44. result.split('\n')
  45. .filter(v => v.trim() !== '')
  46. .map(v => JSON.parse(v))
  47. );
  48. }
  49. setLoading(false);
  50. })
  51. }, []);
  52. // ------------ Load data -------------
  53. // ---------- window update ------------
  54. React.useEffect(() => {
  55. const updateFn = () => {
  56. setWindowDim([
  57. window.innerWidth,
  58. window.innerHeight
  59. ]);
  60. }
  61. updateFn();
  62. window.addEventListener('resize', updateFn);
  63. return () => window.removeEventListener('resize', updateFn);
  64. }, []);
  65. // ---------- window update ------------
  66. return (
  67. <React.Fragment>
  68. {loading &&
  69. <div className="loadingIndicator">
  70. <div className="loadingSpinner">
  71. <div className="loader">Loading...</div>
  72. </div>
  73. <div ref={progressRef}> Downloading 0% ...</div>
  74. </div>}
  75. <StockHeatmap ref={heatmapRef} width={windowDim[0]} height={windowDim[1]} />
  76. <div className="btnContainer">
  77. <button onClick={() => { if (heatmapRef.current !== null) heatmapRef.current.setZoomLevel(60) }}>zoom 1 minute</button>
  78. <button onClick={() => { if (heatmapRef.current !== null) heatmapRef.current.setZoomLevel(60 * 2) }}>zoom 2 minutes</button>
  79. <button onClick={() => { if (heatmapRef.current !== null) heatmapRef.current.setZoomLevel(60 * 3) }}>zoom 3 minutes</button>
  80. <button onClick={() => { if (heatmapRef.current !== null) heatmapRef.current.setZoomLevel(60 * 4) }}>zoom 4 minutes</button>
  81. <button onClick={() => { if (heatmapRef.current !== null) heatmapRef.current.setZoomLevel(60 * 5) }}>zoom 5 minutes</button>
  82. <button onClick={() => { if (heatmapRef.current !== null) heatmapRef.current.setZoomLevel(60 * 10) }}>zoom 10 minutes</button>
  83. </div>
  84. </React.Fragment>
  85. )
  86. }