Added caching for render sheet viewport for O(n)

This commit is contained in:
Eugene 2023-07-24 16:35:38 +03:00
parent 3f896f5603
commit 81bf284591
4 changed files with 124 additions and 44 deletions

View File

@ -11,6 +11,7 @@ import { Styles } from "./modules/styles";
import { Viewport } from "./modules/viewport";
import './scss/main.scss'
import { createSampleConfig, createSampleData } from "./utils/createData";
import { Cache, CachedColumn, CachedRow } from "./modules/cache";
/*
! Component structure
@ -41,21 +42,23 @@ export class Spreadsheet {
public data: Cell[][]
public viewport: Viewport
public selection: Selection
public cache: Cache
constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties) {
const config = createSampleConfig(750, 750)
const config = createSampleConfig(10000, 600)
if (props?.view) {
config.view = props.view
}
this.config = new Config(config)
this.sheet = new Sheet(this)
const data = createSampleData(750, 750)
const data = createSampleData(10000, 600)
this.table = new Table(this)
this.scroller = new Scroller(this)
this.toolbar = new Toolbar(this)
this.header = new Header(this)
this.editor = new Editor(this)
this.cache = this.getInitialCache()
this.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect())
this.selection = new Selection()
@ -66,6 +69,42 @@ export class Spreadsheet {
this.appendTableToTarget(target)
}
private getInitialCache(): Cache {
const cachedCols: CachedColumn[] = []
let currentWidth = 0
for(let i = 0; i <= this.config.columns.length - 1; i++) {
const col = this.config.columns[i]
currentWidth += col.width
const cacheCol = new CachedColumn({
xPos: currentWidth,
colIdx: i
})
cachedCols.push(cacheCol)
}
const cachedRows: CachedRow[] = []
let currentHeight = 0
for(let i = 0; i <= this.config.rows.length - 1; i++) {
const row = this.config.rows[i]
currentHeight += row.height
const cacheRow = new CachedRow({
yPos: currentHeight,
rowIdx: i
})
cachedRows.push(cacheRow)
}
const cache = new Cache({
columns: cachedCols,
rows: cachedRows
})
console.log("CACHE: ", cache)
console.log("CONFIG: ", this.config)
return cache
}
private buildComponent(): void {
const content = document.createElement('div') //* Abstract

67
src/modules/cache.ts Normal file
View File

@ -0,0 +1,67 @@
export interface CachedColumnProperties {
xPos: number
colIdx: number
}
export class CachedColumn {
xPos: number
colIdx: number
constructor(props: CachedColumnProperties) {
this.xPos = props.xPos
this.colIdx = props.colIdx
}
}
export interface CachedRowProperties {
yPos: number
rowIdx: number
}
export class CachedRow {
yPos: number
rowIdx: number
constructor(props: CachedRowProperties) {
this.yPos = props.yPos
this.rowIdx = props.rowIdx
}
}
export interface CacheConstructorProps {
columns: CachedColumn[]
rows: CachedRow[]
}
export class Cache {
public columns: CachedColumn[]
public rows: CachedRow[]
constructor(initial: CacheConstructorProps) {
this.columns = initial.columns
this.rows = initial.rows
}
public getRowByYCoord(y: number): number {
let rowIdx = 0;
for (let i = 0; i < this.rows.length; i++) {
if (y <= this.rows[i].yPos) { //* Intersection detect
rowIdx = i;
break;
}
}
return rowIdx;
}
public getColumnByXCoord(x: number): number {
let colIdx = 0;
for (let i = 0; i < this.columns.length; i++) {
if (x <= this.columns[i].xPos) { //* Intersection detect
colIdx = i;
break;
}
}
return colIdx;
}
}

View File

@ -55,49 +55,23 @@ export class Viewport {
/** Get index of first row in viewport */
private getFirstRow(): number {
let rowIdx = 0
for (let idx = 0, currHeight = 0; currHeight <= this.top; idx++) {
currHeight += this.root.config.rows[idx].height
rowIdx = idx
}
let rowIdx = this.root.cache.getRowByYCoord(this.top)
return rowIdx
}
private getLastRow(): number {
let rowIdx = this.getFirstRow()
let height = this.top
while (height <= this.bottom) {
height += this.root.config.rows[rowIdx].height
if (height >= this.bottom) break;
rowIdx++;
}
let rowIdx = this.root.cache.getRowByYCoord(this.bottom)
return rowIdx
}
private getFirstCol(): number {
let colIdx = 0;
let currWidth = 0
while (currWidth <= this.left) {
currWidth += this.root.config.columns[colIdx].width
if (currWidth >= this.left) break;
colIdx += 1
}
let colIdx = this.root.cache.getColumnByXCoord(this.left)
return colIdx
}
private getLastCol(): number {
let colIdx = this.getFirstCol()
let width = this.left
while (width <= this.right) {
width += this.root.config.columns[colIdx].width
if (width >= this.right) break;
colIdx++;
}
let colIdx = this.root.cache.getColumnByXCoord(this.right)
return colIdx
}