两个图表的弹性框溢出屏幕

Flex box of two charts is overflowing screen

我的页面上有两个图表。它们一起通过 Flex(一个 css flexbox)占据了整个屏幕高度。第一个图表可通过 Accordion.

折叠

我们如何才能让第一个图表占满屏幕高度的 30%,而第二个图表占满剩余的 ~70%?

当这两个图表是页面上 唯一 的东西时,我能够成功地做到这一点:

// This works well.
<Flex direction="column" height="100vh">
  <Accordion allowToggle>
    <AccordionItem>
      <h2>
        <AccordionButton
          h={0}
          borderRadius="md"
          borderWidth="0px"
          _focus={{ boxShadow: "none" }}
        >
          <Box
            textAlign="left"
            h={3}
            _focus={{ boxShadow: "none" }}
          ></Box>
          <AccordionIcon />
        </AccordionButton>
      </h2>
      <AccordionPanel p="0">
        <Box height="30vh">
          <ThreeDataPoint />
        </Box>
      </AccordionPanel>
    </AccordionItem>
  </Accordion>
  <Box flex="1">
    <ThreeDataPoint />
  </Box>
</Flex>

但是,如果我将行和列弹性框组合在一起,它就不起作用了。第二个图表溢出屏幕的高度。

Here's the CODESANDBOX

这是截图:

图表高度是在页面呈现时计算的,因此切换顶部图表后不会重新计算底部图表高度。您需要采取变通办法来触发事件以重新计算第二个图表的高度。您可以使用 <Accordion>onChange 事件来切换状态,并根据状态变化将您的第二个图表包装成高度 100vh70vh<Box>

import * as React from "react";
import { render } from "react-dom";
import "./styles.css";
import { ChakraProvider } from "@chakra-ui/react";
import BasicLineSeries from "./BasicLineSeries";
import {
  Box,
  Accordion,
  AccordionButton,
  AccordionItem,
  AccordionIcon,
  AccordionPanel,
  Flex,
  Text
} from "@chakra-ui/react";

const ThreeDataPoint = () => (
  <BasicLineSeries
    data={[
      {
        close: 120,
        open: 120,
        high: 140,
        low: 100,
        date: new Date(2020, 7, 8, 10, 0, 0, 0),
        volume: 1_000_000
      },
      {
        close: 140,
        open: 120,
        high: 150,
        low: 100,
        date: new Date(2020, 7, 8, 10, 1, 0, 0),
        volume: 1_000_000
      },
      {
        close: 120,
        open: 120,
        high: 140,
        low: 100,
        date: new Date(2020, 7, 8, 10, 2, 0, 0),
        volume: 1_000_000
      }
    ]}
  />
);

const Test = () => {
  const [expended, onExpend] = React.useState(false);

  return (
    <ChakraProvider>
      <>
        <Flex direction="column" height="100vh">
          <Flex flex="1" direction="row">
            <div>123456789010</div>
            <Flex flex="1" direction="column">
              <Accordion
                allowToggle
                onChange={(e) => {
                  if (e === 0) {
                    onExpend(true);
                  } else {
                    onExpend(false);
                  }
                }}
              >
                <AccordionItem>
                  <h2>
                    <AccordionButton
                      h={0}
                      borderRadius="md"
                      borderWidth="0px"
                      _focus={{ boxShadow: "none" }}
                    >
                      <Box
                        textAlign="left"
                        h={3}
                        _focus={{ boxShadow: "none" }}
                      ></Box>
                      <AccordionIcon />
                    </AccordionButton>
                  </h2>
                  <AccordionPanel p="0">
                    <Box height="30vh">
                      <ThreeDataPoint />
                    </Box>
                  </AccordionPanel>
                </AccordionItem>
              </Accordion>
              <Box flex={expended ? 2 : 3}>
                <ThreeDataPoint />
              </Box>
            </Flex>
          </Flex>
        </Flex>
      </>
    </ChakraProvider>
  );
};

const rootElement = document.getElementById("root");
render(<Test />, rootElement);

我对您的代码进行了一些更改,试图获得令人满意的结果,使两个图表保持在 100vh 最大高度并避免滚动。

第二个图表的高度将自动调整,根据第一个图表是否折叠,尽可能多地填充space。

下面是我在您的 styles.css 文件中添加的一些样式(就在您的 .test class 下方):

.flex-wrapper {
  display: grid !important;
  grid-auto-flow: column;
  grid-auto-columns: max-content auto;
  gap: 15px;
  padding: 15px;
  max-height: 100%;
  width: 100%;
}

.accordion-box-container {
  display: grid !important;
  grid-template-rows: min-content auto;
  gap: 15px;
  overflow-y: hidden;
  width: 100%;
}

.accordion-wrapper {
  height: 100%;
}

.accordion-title {
  display: flex;
  align-items: center;
  padding: 5px 0;
  height: auto;
}

.accordion-button {
  width: min-content !important;
  margin-left: 5px;
}

.graph-wrapper {
  height: 100%;
}

.graph-wrapper div {
  height: 100% !important;
}

与此同时,我从 index.tsx 中的 jsx 中删除了一些 bootstrap classes 并将上面的 css classes 添加到适当的组件:

render(
  <ChakraProvider>
    <>
      <Flex direction="column" height="100vh" className="flex-wrapper">
        <div>123456789010</div>
        <Flex>
          <Box className="accordion-box-container">
            <Accordion className="accordion-wrapper" allowToggle>
              <AccordionItem>
                <h2 className="accordion-title">
                  <AccordionButton
                    className="accordion-button"
                    borderRadius="md"
                    borderWidth="0px"
                    _focus={{ boxShadow: "none" }}
                  >
                    <Box
                      textAlign="left"
                      h={3}
                      _focus={{ boxShadow: "none" }}
                    ></Box>
                    <AccordionIcon />
                  </AccordionButton>
                </h2>
                <AccordionPanel p="0">
                  <Box height="30vh">
                    <ThreeDataPoint />
                  </Box>
                </AccordionPanel>
              </AccordionItem>
            </Accordion>
            <div className="graph-wrapper">
              <ThreeDataPoint />
            </div>
          </Box>
        </Flex>
      </Flex>
    </>
  </ChakraProvider>,
  rootElement
);

最后,我不得不在 BasicLineSeries.tsx 中删除您对尺寸的限制,这将对两个图表强制执行最小高度,从而无法在渲染后调整它们的高度(仅更改了导出语句):

export default withSize()(
  withDeviceRatio()(BasicLineSeries)
);

请尝试自行测试,如果这能满足您的要求,请告诉我。如果需要其他内容,请对其进行评论,我会尽力相应地调整我的解决方案。