Open sadr0b0t opened 7 years ago
Для начала, что не сработало.
this.component = ReactDOM.render(element, this.container, callback);
Но толку от него нет, т.к. рендер не вызывается при изменении размера окна. Здесь можно было еще что-то придумать, но нарисовались новые варианты.
React “after render” code? http://stackoverflow.com/questions/26556436/react-after-render-code
Below is an example component. I want to be able to set app-content's height to be 100% of the window minus the size of the ActionBar and BalanceBar, but how do I know when everything is rendered and where would I put the calculation stuff in this React Class?
ответ
In modern browsers you can use flexbox to do this better. Otherwise Harborhoffer's answer.
A Complete Guide to Flexbox https://css-tricks.com/snippets/css/a-guide-to-flexbox/
flex-basis https://css-tricks.com/almanac/properties/f/flex-basis/
How can I make my flexbox layout take 100% vertical space? http://stackoverflow.com/questions/23090136/how-can-i-make-my-flexbox-layout-take-100-vertical-space
Вроде как похоже на то, что нужно, но по факту вылезли проблемы:
Еще какой-то дискасс о том, что чел не может сделать таб 100% высоты экрана в MaterialUI https://github.com/callemall/material-ui/issues/2085
Еще прям целый трактат о том, как делать полноростовые веб-приложения 2011 года (похоже, совсем устарел)
Full-height app layouts: A CSS trick to make it easier http://blog.stevensanderson.com/2011/10/05/full-height-app-layouts-a-css-trick-to-make-it-easier/
Flexbox and vertical scroll in a full-height app using NEWER flexbox api http://stackoverflow.com/questions/14962468/flexbox-and-vertical-scroll-in-a-full-height-app-using-newer-flexbox-api/34362676
CSS3 Flexbox full-height app and overflow http://stackoverflow.com/questions/9251447/css3-flexbox-full-height-app-and-overflow
flexbox for svg in react https://dlmanning.github.io/react-flexbox-svg/ https://github.com/dlmanning/react-flexbox-svg
Containing a SVG image within Flexbox http://stackoverflow.com/questions/37242454/containing-a-svg-image-within-flexbox http://codepen.io/anon/pen/eZoXgE демо исправленного решения: https://i.stack.imgur.com/jokCs.gif
Подробнее про vh (viewport unit)
Простой способ растянуть блок на всю высоту экрана, или CSS3 Viewport Units https://habrahabr.ru/post/243161/
Единицы измерения vh и vw vh и vw можно расшифровать, как viewport height и viewport width — высота и ширина области просмотра соответственно. 1vh равен одному проценту от высоты области просмотра, 1vw равняется одному проценту от ширины области просмотра.
Единицы измерения vmin и vmax vmin и vmax расшифровывается, как viewport minimal и viewport maximal. 1vmin сравнивает значения 1vh и 1vw, выбирая меньшее из них. 1vmax делает то же самое, но выбирает большее из двух значений. Иначе говоря, если у смартфона ширина экрана меньше высоты, то vmin будет рассчитываться относительно ширины, а vmax будет рассчитываться относительно высоты экрана.
Варианты:
Назначить нужную высоту тегу SVG напрямую
<svg style={{backgroundColor: "blue", width: "100%", height: "calc(100vh - 150px)"}} .../>
Назначить нужную высоту обрамляющему диву, в svg в таком случае нужно выставить ширину и высоту 100%
В обоих случаях картинка будет масштабироваться, как нужно: при изменении размера экрана займет максимальное возможное пространство и по ширине и по высоте без необходимости включения скролла.
И да, старые атрибуты SVG x,y,width,height (передавались через параметр screen) все порезали, вместо них CSS.
Замечания
Попытка ограничить минимальный размер (чтобы все-таки включался скролл) с minHeight: 40 не стаботал, нужно еще поиграть с вариантами (или забить фиг с ним)
Для того, чтобы убрать из целевой высоты блока высоту остальных элементов, которые занимают вертикальную площадь экрана (верхняя панель подключения, табы, нижняя панель статуса), мы делаем "calc(100vh - 150px)" (вычитаем из 100% видимой высоты 150пикселей). При такой записи по факту получается ровно то, что нужно, только пока не очень ясно, почему именно 150 пикселей дают этот результат (все вертикальные элементы вместе взятые столько не занимают близко - нижняя панель, например, всего 15px). Это или какой-то нюанс с совмещением единиц измерения в calc или какой-то глюк в реализации.
По CSS calc: важно ставить пробелы вокруг знака математической операции, иначе парсер реально этот атрибут не воспринимает.
Математика разметки с помощью CSS: разбираемся с calc https://habrahabr.ru/post/243821/
Далее: теперь нужно сделать все то же самое, только чтобы по высоте масштабировался и вписывался не только элемент с картинкой SVG, но обрамляющие его кнопки управления со всем 3хколоночным лэйаутом и нижней строкой.
Есть ощущение, что от display: table придется отказаться. Возможно, в этом поможет CSS Grid.
A Complete Guide to Grid https://css-tricks.com/snippets/css/complete-guide-grid/
Нормальный пост про flexbox (разжевано, что такое flex-shink, flex-grow, flex-basic, в отличие от "комплит гайда", где от них только названия) Практическое применение FlexBox https://habrahabr.ru/post/242545/
Короче, 3 колонки:
колонка посередине
Правильное решение:
<div style={{display: "flex", flexFlow: "row"}}>
<div style={{flexBasis:"0px"}}>кнопки слева</div>
<div style={{flexBasis:"100%", textAlign: "center"}}>
<DekartCanvas style={{width: "100%", height: "calc(100vh - 250px)"}}/>
<div>еще кнопки</div>
</div>
<div style={{flexBasis:"0px"}}>кнопки справа</div>
</div>
Т.е. по краям выставляем flex-basis 0px (минимальная ширина колонки - уже кнопок их див все равно не сожмется), а для средней - 100% (все оставшееся место). Аналогичного результата еще можно достигнуть, если поиграть немного с полем flex-grow (по краям выставить 0, а по центру 1: тогда по центру не обязательно ставить flex-basis 100%, но для крайних колонок все равно придется выставить минимальную ширину flex-basis, иначе на auto их растянет в ширину в ряд кнопок вместо столбца).
DekartCanvas без ограничения по высоте при любом размере окна заполняют всю ширину и устраивают нижний скролл.
Вынес стиль для DekartCanvas внутри CncTaskControl в отдельное поле dekartStyle, правильную высоту нужно указывать здесь (это логично, т.к. значение разницы между необходимой высотой поля и реальным размером экрана будет известно только на самом верхнем уровне, где добавляются всякие верхние и нижние панели).
<CncTaskControl babblerCnc={babblerCnc1}
dekartStyle={{width: "100%", height: "calc(100vh - 250px)", minHeight:350}}
fold={{dimX: 300, dimY:216, dimZ:100}}/>
minHeight, кстати, в такой верстке тоже заработала.
Осталось понять, откуда взялись эти безумные 250px (это уже с кнопками, без кнопок было 150px) вместо 40-50 реальных пикселей, занимаемых от высоты экрана горизонтальными панелями, максимум.
Нужно рисовать рабочее поле по всей высоте окна: растягивать в высоту, если есть много свободного места, сжимать, если места не достаточно (можно до варианта minHeight).
Сейчас ширина рабочего поля меняется автоматом за окном - для этого оказалось достаточным задать для тега svg width="100%". В случае с высотой height="100%" этот прикол не работает (точнее работает, но поле растягивается не на свободную видимую область экрана, а, похоже, просто на высоту окна, и нижняя часть уходит со скроллом вниз).
Вариант - задавать фиксированную высоту 450px работает, но не очень красивый - если на экране будет много вертикального места, оно не будет использовано для рисования рабочей области.
Если с CSS этот трюк провернуть не получится, можно попробовать сделать хак на JS.
Здесь обсуждают аналогичную проблему
How to animate height , when element heght is not fixed https://github.com/chenglou/react-motion/issues/62
и, судя по коментам, решение на чистом CSS тоже не находят. На JS тоже не все просто - чтобы получить значение высоты для дива, нужно дать страничке хотя бы один раз отрисоваться, иначе, будет 0. А для первого рендера подготовить значение по умолчанию.