Use CSS content-visibility to improve rendering performance by hiding offscreen grid cells
This commit is contained in:
parent
4e703fdfcc
commit
c37538d611
|
@ -21,6 +21,7 @@
|
||||||
export let invertX = false
|
export let invertX = false
|
||||||
export let invertY = false
|
export let invertY = false
|
||||||
export let contentLines = 1
|
export let contentLines = 1
|
||||||
|
export let hidden = false
|
||||||
|
|
||||||
const emptyError = writable(null)
|
const emptyError = writable(null)
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@
|
||||||
{focused}
|
{focused}
|
||||||
{selectedUser}
|
{selectedUser}
|
||||||
{readonly}
|
{readonly}
|
||||||
|
{hidden}
|
||||||
error={$error}
|
error={$error}
|
||||||
on:click={() => focusedCellId.set(cellId)}
|
on:click={() => focusedCellId.set(cellId)}
|
||||||
on:contextmenu={e => menu.actions.open(cellId, e)}
|
on:contextmenu={e => menu.actions.open(cellId, e)}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
export let defaultHeight = false
|
export let defaultHeight = false
|
||||||
export let center = false
|
export let center = false
|
||||||
export let readonly = false
|
export let readonly = false
|
||||||
|
export let hidden = false
|
||||||
|
|
||||||
$: style = getStyle(width, selectedUser)
|
$: style = getStyle(width, selectedUser)
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
class:error
|
class:error
|
||||||
class:center
|
class:center
|
||||||
class:readonly
|
class:readonly
|
||||||
|
class:hidden
|
||||||
class:default-height={defaultHeight}
|
class:default-height={defaultHeight}
|
||||||
class:selected-other={selectedUser != null}
|
class:selected-other={selectedUser != null}
|
||||||
class:alt={rowIdx % 2 === 1}
|
class:alt={rowIdx % 2 === 1}
|
||||||
|
@ -81,6 +83,9 @@
|
||||||
.cell.center {
|
.cell.center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.cell.hidden {
|
||||||
|
content-visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cell border */
|
/* Cell border */
|
||||||
.cell.focused:after,
|
.cell.focused:after,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
isDragging,
|
isDragging,
|
||||||
dispatch,
|
dispatch,
|
||||||
rows,
|
rows,
|
||||||
|
columnRenderMap,
|
||||||
} = getContext("grid")
|
} = getContext("grid")
|
||||||
|
|
||||||
$: rowSelected = !!$selectedRows[row._id]
|
$: rowSelected = !!$selectedRows[row._id]
|
||||||
|
@ -51,6 +52,7 @@
|
||||||
selectedUser={$selectedCellMap[cellId]}
|
selectedUser={$selectedCellMap[cellId]}
|
||||||
width={column.width}
|
width={column.width}
|
||||||
contentLines={$contentLines}
|
contentLines={$contentLines}
|
||||||
|
hidden={!$columnRenderMap[column.name]}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
refreshing,
|
refreshing,
|
||||||
config,
|
config,
|
||||||
filter,
|
filter,
|
||||||
|
columnRenderMap,
|
||||||
} = getContext("grid")
|
} = getContext("grid")
|
||||||
|
|
||||||
let visible = false
|
let visible = false
|
||||||
|
@ -224,6 +225,7 @@
|
||||||
topRow={offset === 0}
|
topRow={offset === 0}
|
||||||
invertX={columnIdx >= $columnHorizontalInversionIndex}
|
invertX={columnIdx >= $columnHorizontalInversionIndex}
|
||||||
{invertY}
|
{invertY}
|
||||||
|
hidden={!$columnRenderMap[column.name]}
|
||||||
>
|
>
|
||||||
{#if column?.schema?.autocolumn}
|
{#if column?.schema?.autocolumn}
|
||||||
<div class="readonly-overlay">Can't edit auto column</div>
|
<div class="readonly-overlay">Can't edit auto column</div>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { derived } from "svelte/store"
|
import { derived, get } from "svelte/store"
|
||||||
import {
|
import {
|
||||||
MaxCellRenderHeight,
|
MaxCellRenderHeight,
|
||||||
MaxCellRenderWidthOverflow,
|
MaxCellRenderWidthOverflow,
|
||||||
|
MinColumnWidth,
|
||||||
ScrollBarSize,
|
ScrollBarSize,
|
||||||
} from "../lib/constants"
|
} from "../lib/constants"
|
||||||
|
|
||||||
|
@ -44,6 +45,47 @@ export const deriveStores = context => {
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Derive visible columns
|
||||||
|
const scrollLeftRounded = derived(scrollLeft, $scrollLeft => {
|
||||||
|
const interval = MinColumnWidth
|
||||||
|
return Math.round($scrollLeft / interval) * interval
|
||||||
|
})
|
||||||
|
const columnRenderMap = derived(
|
||||||
|
[visibleColumns, scrollLeftRounded, width],
|
||||||
|
([$visibleColumns, $scrollLeft, $width]) => {
|
||||||
|
if (!$visibleColumns.length) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
let startColIdx = 0
|
||||||
|
let rightEdge = $visibleColumns[0].width
|
||||||
|
while (
|
||||||
|
rightEdge < $scrollLeft &&
|
||||||
|
startColIdx < $visibleColumns.length - 1
|
||||||
|
) {
|
||||||
|
startColIdx++
|
||||||
|
rightEdge += $visibleColumns[startColIdx].width
|
||||||
|
}
|
||||||
|
let endColIdx = startColIdx + 1
|
||||||
|
let leftEdge = rightEdge
|
||||||
|
while (
|
||||||
|
leftEdge < $width + $scrollLeft &&
|
||||||
|
endColIdx < $visibleColumns.length
|
||||||
|
) {
|
||||||
|
leftEdge += $visibleColumns[endColIdx].width
|
||||||
|
endColIdx++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only update the store if different
|
||||||
|
let next = {}
|
||||||
|
$visibleColumns
|
||||||
|
.slice(Math.max(0, startColIdx), endColIdx)
|
||||||
|
.forEach(col => {
|
||||||
|
next[col.name] = true
|
||||||
|
})
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Determine the row index at which we should start vertically inverting cell
|
// Determine the row index at which we should start vertically inverting cell
|
||||||
// dropdowns
|
// dropdowns
|
||||||
const rowVerticalInversionIndex = derived(
|
const rowVerticalInversionIndex = derived(
|
||||||
|
@ -87,6 +129,7 @@ export const deriveStores = context => {
|
||||||
scrolledRowCount,
|
scrolledRowCount,
|
||||||
visualRowCapacity,
|
visualRowCapacity,
|
||||||
renderedRows,
|
renderedRows,
|
||||||
|
columnRenderMap,
|
||||||
rowVerticalInversionIndex,
|
rowVerticalInversionIndex,
|
||||||
columnHorizontalInversionIndex,
|
columnHorizontalInversionIndex,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue