Dynamic grid row height — различия между версиями
Материал из YourcmcWiki
(Новая страница: «https://www.ag-grid.com/javascript-grid-row-height/ "By default, the grid will display rows at 25px. You can change this for each row individually to give each r…») |
м |
||
(не показаны 2 промежуточные версии этого же участника) | |||
Строка 1: | Строка 1: | ||
+ | …Impossible in almost all JS grids with virtual scrolling. | ||
+ | |||
https://www.ag-grid.com/javascript-grid-row-height/ | https://www.ag-grid.com/javascript-grid-row-height/ | ||
− | + | «By default, the grid will display rows at 25px. You can change this for each row individually to give each row a different height.» | |
+ | |||
+ | «Grid, fixed row height (no word wrap, no multi line) — Grid — Kendo UI …» | ||
+ | |||
+ | But we have a solution :) | ||
+ | |||
+ | * Use reasonable fixed minimum row height | ||
+ | * Always render (screen/minHeight) last rows | ||
+ | * Find maximum possible viewport start (in units of item number + % of item) | ||
+ | * Measure average height of last rows | ||
+ | * {{cmd|1=avgHeight = max(minHeight, lastRowAvgHeight)}} | ||
+ | * {{cmd|1=targetHeight = avgHeight*rowCount + headerHeight}} | ||
+ | * Set sizer to targetHeight | ||
+ | * {{cmd|1=scrollPos = targetHeight > offsetHeight ? min(1, scrollTop / (targetHeight - offsetHeight)) : 0}} | ||
+ | * First visible item will be {{cmd|1=Math.floor(scrollPos*maxPossibleViewportStart)}} | ||
+ | * Additional scroll offset will be {{cmd|1=itemOffset = scrollPos*maxPossibleViewportStart - Math.floor(scrollPos*maxPossibleViewportStart)*firstVisibleItemHeight}} | ||
+ | * First (top) placeholder height will be {{cmd|1=scrollTop-firstVisibleItemHeight+itemOffset}} | ||
+ | * Second (middle) placeholder height will be {{cmd|1=avgHeight*nodeCount - sum(heights of all rendered rows) - (first placeholder height)}} | ||
+ | |||
+ | I.e. it’s like: | ||
+ | |||
+ | <pre> | ||
+ | state = { avgRowHeight, topPlaceholderHeight, firstVisibleItem, middleItemCount, middlePlaceholderHeight, lastItemCount, itemScrollTop, viewportHeight } | ||
+ | |||
+ | <top placeholder> | ||
+ | middleItemCount ? <middle items> : null | ||
+ | middlePlaceholderHeight ? <middle placeholder> : null | ||
+ | <last items> | ||
+ | </pre> | ||
+ | |||
+ | * Initial render: 0 / 0 / 0 / 0 | ||
+ | * Render 1: set viewportHeight, set lastItemCount => 0 / 0 / 0 / set | ||
+ | * Render 2: set itemScrollHeight (scroll height in items+%), set avgRowHeight, set sizer targetHeight, set firstVisibleItem => set / set / 0 / set | ||
+ | * Render 3: set middlePlaceholderHeight, (for a table with fixed column: sync fixed column row heights) => set / set / set / set | ||
+ | * After that each scroll takes 2 renders to complete (re-render items, re-set placeholder height) | ||
+ | * If it’s not a table then it’s possible to do absolute positioning instead of placeholders and only do a single render by positioning last items at the bottom of scroll container, because we already know targetHeight before the first render of two |
Текущая версия на 14:19, 8 октября 2018
…Impossible in almost all JS grids with virtual scrolling.
https://www.ag-grid.com/javascript-grid-row-height/
«By default, the grid will display rows at 25px. You can change this for each row individually to give each row a different height.»
«Grid, fixed row height (no word wrap, no multi line) — Grid — Kendo UI …»
But we have a solution :)
- Use reasonable fixed minimum row height
- Always render (screen/minHeight) last rows
- Find maximum possible viewport start (in units of item number + % of item)
- Measure average height of last rows
- avgHeight = max(minHeight, lastRowAvgHeight)
- targetHeight = avgHeight*rowCount + headerHeight
- Set sizer to targetHeight
- scrollPos = targetHeight > offsetHeight ? min(1, scrollTop / (targetHeight - offsetHeight)) : 0
- First visible item will be Math.floor(scrollPos*maxPossibleViewportStart)
- Additional scroll offset will be itemOffset = scrollPos*maxPossibleViewportStart - Math.floor(scrollPos*maxPossibleViewportStart)*firstVisibleItemHeight
- First (top) placeholder height will be scrollTop-firstVisibleItemHeight+itemOffset
- Second (middle) placeholder height will be avgHeight*nodeCount - sum(heights of all rendered rows) - (first placeholder height)
I.e. it’s like:
state = { avgRowHeight, topPlaceholderHeight, firstVisibleItem, middleItemCount, middlePlaceholderHeight, lastItemCount, itemScrollTop, viewportHeight } <top placeholder> middleItemCount ? <middle items> : null middlePlaceholderHeight ? <middle placeholder> : null <last items>
- Initial render: 0 / 0 / 0 / 0
- Render 1: set viewportHeight, set lastItemCount => 0 / 0 / 0 / set
- Render 2: set itemScrollHeight (scroll height in items+%), set avgRowHeight, set sizer targetHeight, set firstVisibleItem => set / set / 0 / set
- Render 3: set middlePlaceholderHeight, (for a table with fixed column: sync fixed column row heights) => set / set / set / set
- After that each scroll takes 2 renders to complete (re-render items, re-set placeholder height)
- If it’s not a table then it’s possible to do absolute positioning instead of placeholders and only do a single render by positioning last items at the bottom of scroll container, because we already know targetHeight before the first render of two