#javascript #css #reactjs #flexbox #chakra-ui
Вопрос:
У меня на странице есть две диаграммы. Вместе они занимают всю высоту экрана Flex
(css flexbox). Первая диаграмма складывается через an 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>
Однако, если я объединю окно гибкого трубопровода строки и столбца вместе, это не сработает. Вторая диаграмма превышает высоту экрана.
И вот скриншот:
Комментарии:
1. возможно, использование чакры
sx
для добавления селектора «первый ребенок»/»n-й ребенок» поможет
Ответ №1:
Я внес некоторые изменения в ваш код, пытаясь добиться несколько удовлетворительного результата, который позволяет сохранить обе диаграммы на этой 100vh
максимальной высоте и избежать прокрутки.
Высота второй диаграммы будет автоматически изменена, заполняя как можно больше свободного места в зависимости от того, свернута первая диаграмма или нет.
Вот некоторые стили, которые я добавил в ваш файл styles.css (прямо под вашим .test
классом):
.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;
}
Тем временем я удалил некоторые классы начальной загрузки из вашего jsx index.tsx
и добавил классы css выше в соответствующие компоненты:
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):
export default withSize()(
withDeviceRatio()(BasicLineSeries)
);
Пожалуйста, попробуйте проверить это самостоятельно и сообщите мне, соответствует ли это вашим требованиям. Если понадобится что-то еще, прокомментируйте это, и я сделаю все возможное, чтобы соответствующим образом скорректировать свое решение.
Комментарии:
1. Привет, Кевин. Мне нужно, чтобы номер 123456789010 был на левой стороне аккордеона. Они должны быть отдельными колоннами. В моем приложении «123456789010» на самом деле является еще одним компонентом. Я просто поместил туда какой-то простой текст в качестве заполнителя для этого примера. Вот почему я использовал в своем примере гибкое окно строк. Мне интересно, есть ли простой способ изменить ваше решение, чтобы учесть это?
2. @ABC Да, я посмотрю на это, я просто неправильно понял ваши намерения. 🙂 Должны ли обе диаграммы находиться в одном столбце, отделенном от текста?
3. Я сожалею об этом, я должен был прояснить это в операции.
4. @ABC Закончил с правками, пожалуйста, проверьте предварительные просмотры и скажите мне, это то, что вы ожидали.
5. @ABC Рад был помочь, пожалуйста, отметьте это как решение вашего вопроса, если это сработает для вас.
Ответ №2:
Высота диаграмм рассчитывается при отображении страницы, поэтому после переключения верхнего графика высота нижнего графика не будет пересчитана. Вам нужно выполнить обходной путь, чтобы вызвать событие для пересчета высоты второго графика. Вы можете использовать onChange
событие для <Accordion>
переключения состояния и обернуть вторую диаграмму по <Box>
высоте 100vh
или 70vh
на основе изменения состояния.
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);
Комментарии:
1. Почти, но не совсем. Нижняя часть второго графика (ось x) обрезается. 30vh 70vh слишком велики, потому что они не учитывают ничего выше обоих графиков (в данном случае раскрывающееся меню аккордеона).
2. Это был быстрый пример того, как вы можете решить свою проблему. Я уверен, что у вас на странице будет какой-то верхний/нижний колонтитул, поэтому вам также следует учитывать это
3. Но даже при отсутствии верхнего и нижнего колонтитулов проблема не решена. Решение, которое вы предлагаете, вызывает переполнение страницы из-за самого аккордеона
4. Это странно, но у меня это не работает. Расширенный аккордеон все еще переполнен. См.: codesandbox.io/s/pedantic-meadow-ipx0b?file=/src/index.tsx
5. Какой браузер вы используете?