Added full support of rendering table
Todo: test with resize
This commit is contained in:
parent
25e698a658
commit
ee85d771a4
|
|
@ -1,5 +1,12 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
|
||||
export interface ViewportRect {
|
||||
top: number
|
||||
left: number
|
||||
right: number
|
||||
bottom: number
|
||||
}
|
||||
|
||||
export class Scroller {
|
||||
element: HTMLDivElement
|
||||
private verticalScroller: HTMLDivElement
|
||||
|
|
@ -17,6 +24,29 @@ export class Scroller {
|
|||
this.element.style.width = this.root.config.view.width + 'px'
|
||||
|
||||
this.updateScrollerSize() //* Init size set
|
||||
|
||||
this.element.addEventListener('scroll', this.handleScroll)
|
||||
}
|
||||
|
||||
handleScroll = () => {
|
||||
const rect = this.getViewportBoundlingRect()
|
||||
this.root.viewport.updateValues(rect)
|
||||
|
||||
this.root.renderSheet()
|
||||
}
|
||||
|
||||
getViewportBoundlingRect(): ViewportRect {
|
||||
const { scrollTop, scrollLeft } = this.element
|
||||
const { height, width } = this.element.getBoundingClientRect()
|
||||
const bottom = scrollTop + height
|
||||
const right = scrollLeft + width
|
||||
|
||||
return {
|
||||
top: scrollTop,
|
||||
left: scrollLeft,
|
||||
bottom,
|
||||
right
|
||||
}
|
||||
}
|
||||
|
||||
buildComponent() {
|
||||
|
|
|
|||
|
|
@ -33,15 +33,27 @@ export class Sheet {
|
|||
}
|
||||
|
||||
renderSheet() {
|
||||
const {columns, rows} = this.root.config
|
||||
const lastColIdx = columns.length - 1
|
||||
const lastRowIdx = rows.length - 1
|
||||
const firstRowIdx = this.root.viewport.firstRow
|
||||
const lastColIdx = this.root.viewport.lastCol + 3
|
||||
const lastRowIdx = this.root.viewport.lastRow + 3
|
||||
const firstColIdx = this.root.viewport.firstCol
|
||||
|
||||
console.log()
|
||||
|
||||
let rowsCount = 0
|
||||
|
||||
for(let row = firstRowIdx; row <= lastRowIdx; row++) {
|
||||
|
||||
for(let col = firstColIdx; col <= lastColIdx; col++ ) {
|
||||
if(!this.root.config.columns[col] || !this.root.config.rows[row]) break; //* Prevent read undefined
|
||||
|
||||
for(let row = 0; row <= lastRowIdx; row++) {
|
||||
for(let col = 0; col <= lastColIdx; col++ ) {
|
||||
this.renderCell({column: col, row})
|
||||
}
|
||||
|
||||
rowsCount++;
|
||||
}
|
||||
|
||||
console.log(`Rendered ${rowsCount} rows!`)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
export class Viewport {
|
||||
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import { Toolbar } from "./components/toolbar";
|
|||
import { Cell } from "./modules/cell";
|
||||
import { Config, ViewProperties } from "./modules/config";
|
||||
import { Styles } from "./modules/styles";
|
||||
import { Viewport } from "./modules/viewport";
|
||||
import './scss/main.scss'
|
||||
import { createSampleConfig, createSampleData } from "./utils/createData";
|
||||
|
||||
|
|
@ -37,21 +38,24 @@ export class Spreadsheet {
|
|||
public styles: Styles
|
||||
public config: Config
|
||||
public data: Cell[][]
|
||||
public viewport: Viewport
|
||||
|
||||
constructor(target: string | HTMLElement, props?: SpreadsheetConstructorProperties) {
|
||||
const config = createSampleConfig(40, 40)
|
||||
const config = createSampleConfig(150, 150)
|
||||
if(props?.view) {
|
||||
config.view = props.view
|
||||
}
|
||||
|
||||
this.config = new Config(config)
|
||||
this.sheet = new Sheet(this)
|
||||
const data = createSampleData(40, 40)
|
||||
const data = createSampleData(150, 150)
|
||||
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.viewport = new Viewport(this, this.scroller.getViewportBoundlingRect())
|
||||
|
||||
|
||||
this.data = data
|
||||
this.styles = new Styles()
|
||||
|
|
|
|||
|
|
@ -31,11 +31,22 @@ export class Cell {
|
|||
}
|
||||
|
||||
render(root: Spreadsheet) {
|
||||
const {height, width, x, y} = new RenderBox(root.config, this.position)
|
||||
let {height, width, x, y} = new RenderBox(root.config, this.position)
|
||||
const { ctx } = root
|
||||
|
||||
y -= root.viewport.top
|
||||
x -= root.viewport.left
|
||||
|
||||
ctx.clearRect(x, y, width, height)
|
||||
ctx.fillStyle = 'white'
|
||||
ctx.strokeStyle = 'black'
|
||||
ctx.fillRect(x + 1, y + 1, width - 1, height - 1)
|
||||
ctx.strokeRect(x, y, width, height)
|
||||
|
||||
ctx.fillStyle = 'black'
|
||||
ctx.textAlign = 'left'
|
||||
ctx.font = '16px Arial'
|
||||
ctx.textBaseline = 'middle'
|
||||
ctx.fillText(this.displayValue, x + 2, y + height / 2, width)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
import { Spreadsheet } from "../main"
|
||||
|
||||
export type ViewportConstructorProps = {
|
||||
top: number
|
||||
left: number
|
||||
right: number
|
||||
bottom: number
|
||||
}
|
||||
|
||||
export class Viewport {
|
||||
root: Spreadsheet
|
||||
|
||||
top: number
|
||||
left: number
|
||||
right: number
|
||||
bottom: number
|
||||
|
||||
firstRow: number
|
||||
lastRow: number
|
||||
firstCol: number
|
||||
lastCol: number
|
||||
|
||||
constructor(root: Spreadsheet, props: ViewportConstructorProps) {
|
||||
this.root = root
|
||||
|
||||
this.top = props.top
|
||||
this.left = props.left
|
||||
this.right = props.right
|
||||
this.bottom = props.bottom
|
||||
|
||||
this.firstRow = this.getFirstRow()
|
||||
this.lastCol = this.getFirstRow() //!Temp
|
||||
this.firstCol = this.getFirstRow() //!Temp
|
||||
this.lastRow = this.getLastRow()
|
||||
|
||||
this.updateValues({
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: this.root.viewProps.width,
|
||||
bottom: this.root.viewProps.height
|
||||
})
|
||||
}
|
||||
|
||||
updateValues(props: ViewportConstructorProps) {
|
||||
this.top = props.top
|
||||
this.left = props.left
|
||||
this.right = props.right
|
||||
this.bottom = props.bottom
|
||||
|
||||
this.firstRow = this.getFirstRow()
|
||||
this.lastRow = this.getLastRow()
|
||||
this.firstCol = this.getFirstCol()
|
||||
this.lastCol = this.getLastCol()
|
||||
|
||||
console.log({ first: this.firstCol, last: this.lastCol })
|
||||
}
|
||||
|
||||
/** 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
|
||||
}
|
||||
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++;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
return colIdx
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue