Added caching for render sheet viewport for O(n)
This commit is contained in:
parent
3f896f5603
commit
81bf284591
|
|
@ -22,7 +22,7 @@ export class Sheet {
|
||||||
this.element = canvas
|
this.element = canvas
|
||||||
|
|
||||||
const ctx = this.element.getContext('2d')
|
const ctx = this.element.getContext('2d')
|
||||||
if(!ctx) throw new Error('Enable hardware acceleration')
|
if (!ctx) throw new Error('Enable hardware acceleration')
|
||||||
this.ctx = ctx
|
this.ctx = ctx
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -30,17 +30,17 @@ export class Sheet {
|
||||||
getCellByCoords(x: number, y: number): Position {
|
getCellByCoords(x: number, y: number): Position {
|
||||||
let row = 0;
|
let row = 0;
|
||||||
let height = 0
|
let height = 0
|
||||||
while(height <= y) {
|
while (height <= y) {
|
||||||
height += this.root.config.rows[row].height
|
height += this.root.config.rows[row].height
|
||||||
if(height >= y) break;
|
if (height >= y) break;
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
let col = 0;
|
let col = 0;
|
||||||
let width = 0;
|
let width = 0;
|
||||||
while(width <= x) {
|
while (width <= x) {
|
||||||
width += this.root.config.columns[col].width
|
width += this.root.config.columns[col].width
|
||||||
if(width >= x) break;
|
if (width >= x) break;
|
||||||
col++;
|
col++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ export class Sheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCell(position: Position) {
|
renderCell(position: Position) {
|
||||||
const {column, row} = position
|
const { column, row } = position
|
||||||
this.root.data[row][column].render(this.root)
|
this.root.data[row][column].render(this.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,11 +58,11 @@ export class Sheet {
|
||||||
const lastRowIdx = this.root.viewport.lastRow + 3
|
const lastRowIdx = this.root.viewport.lastRow + 3
|
||||||
const firstColIdx = this.root.viewport.firstCol
|
const firstColIdx = this.root.viewport.firstCol
|
||||||
|
|
||||||
for(let row = firstRowIdx; row <= lastRowIdx; row++) {
|
for (let row = firstRowIdx; row <= lastRowIdx; row++) {
|
||||||
for(let col = firstColIdx; col <= lastColIdx; col++ ) {
|
for (let col = firstColIdx; col <= lastColIdx; col++) {
|
||||||
if(!this.root.config.columns[col] || !this.root.config.rows[row]) break; //* Prevent read undefined
|
if (!this.root.config.columns[col] || !this.root.config.rows[row]) break; //* Prevent read undefined
|
||||||
|
|
||||||
this.renderCell({column: col, row})
|
this.renderCell({ column: col, row })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
47
src/main.ts
47
src/main.ts
|
|
@ -11,6 +11,7 @@ import { Styles } from "./modules/styles";
|
||||||
import { Viewport } from "./modules/viewport";
|
import { Viewport } from "./modules/viewport";
|
||||||
import './scss/main.scss'
|
import './scss/main.scss'
|
||||||
import { createSampleConfig, createSampleData } from "./utils/createData";
|
import { createSampleConfig, createSampleData } from "./utils/createData";
|
||||||
|
import { Cache, CachedColumn, CachedRow } from "./modules/cache";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
! Component structure
|
! Component structure
|
||||||
|
|
@ -41,24 +42,26 @@ export class Spreadsheet {
|
||||||
public data: Cell[][]
|
public data: Cell[][]
|
||||||
public viewport: Viewport
|
public viewport: Viewport
|
||||||
public selection: Selection
|
public selection: Selection
|
||||||
|
public cache: Cache
|
||||||
|
|
||||||
constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties) {
|
constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties) {
|
||||||
const config = createSampleConfig(750, 750)
|
const config = createSampleConfig(10000, 600)
|
||||||
if (props?.view) {
|
if (props?.view) {
|
||||||
config.view = props.view
|
config.view = props.view
|
||||||
}
|
}
|
||||||
|
|
||||||
this.config = new Config(config)
|
this.config = new Config(config)
|
||||||
this.sheet = new Sheet(this)
|
this.sheet = new Sheet(this)
|
||||||
const data = createSampleData(750, 750)
|
const data = createSampleData(10000, 600)
|
||||||
this.table = new Table(this)
|
this.table = new Table(this)
|
||||||
this.scroller = new Scroller(this)
|
this.scroller = new Scroller(this)
|
||||||
this.toolbar = new Toolbar(this)
|
this.toolbar = new Toolbar(this)
|
||||||
this.header = new Header(this)
|
this.header = new Header(this)
|
||||||
this.editor = new Editor(this)
|
this.editor = new Editor(this)
|
||||||
|
this.cache = this.getInitialCache()
|
||||||
this.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect())
|
this.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect())
|
||||||
this.selection = new Selection()
|
this.selection = new Selection()
|
||||||
|
|
||||||
|
|
||||||
this.data = data
|
this.data = data
|
||||||
this.styles = new Styles()
|
this.styles = new Styles()
|
||||||
|
|
@ -66,6 +69,42 @@ export class Spreadsheet {
|
||||||
this.appendTableToTarget(target)
|
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 {
|
private buildComponent(): void {
|
||||||
|
|
||||||
const content = document.createElement('div') //* Abstract
|
const content = document.createElement('div') //* Abstract
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -55,49 +55,23 @@ export class Viewport {
|
||||||
|
|
||||||
/** Get index of first row in viewport */
|
/** Get index of first row in viewport */
|
||||||
private getFirstRow(): number {
|
private getFirstRow(): number {
|
||||||
let rowIdx = 0
|
let rowIdx = this.root.cache.getRowByYCoord(this.top)
|
||||||
for (let idx = 0, currHeight = 0; currHeight <= this.top; idx++) {
|
|
||||||
currHeight += this.root.config.rows[idx].height
|
|
||||||
rowIdx = idx
|
|
||||||
}
|
|
||||||
return rowIdx
|
return rowIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
private getLastRow(): number {
|
private getLastRow(): number {
|
||||||
let rowIdx = this.getFirstRow()
|
let rowIdx = this.root.cache.getRowByYCoord(this.bottom)
|
||||||
let height = this.top
|
|
||||||
|
|
||||||
while (height <= this.bottom) {
|
|
||||||
height += this.root.config.rows[rowIdx].height
|
|
||||||
if (height >= this.bottom) break;
|
|
||||||
rowIdx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowIdx
|
return rowIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFirstCol(): number {
|
private getFirstCol(): number {
|
||||||
let colIdx = 0;
|
let colIdx = this.root.cache.getColumnByXCoord(this.left)
|
||||||
let currWidth = 0
|
|
||||||
|
|
||||||
while (currWidth <= this.left) {
|
|
||||||
currWidth += this.root.config.columns[colIdx].width
|
|
||||||
if (currWidth >= this.left) break;
|
|
||||||
colIdx += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return colIdx
|
return colIdx
|
||||||
}
|
}
|
||||||
|
|
||||||
private getLastCol(): number {
|
private getLastCol(): number {
|
||||||
let colIdx = this.getFirstCol()
|
let colIdx = this.root.cache.getColumnByXCoord(this.right)
|
||||||
let width = this.left
|
|
||||||
|
|
||||||
while (width <= this.right) {
|
|
||||||
width += this.root.config.columns[colIdx].width
|
|
||||||
if (width >= this.right) break;
|
|
||||||
colIdx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return colIdx
|
return colIdx
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue