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