Dynamic grid row height
Материал из YourcmcWiki
…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