modern_spreadsheet/src/components/scroller.ts

106 lines
3.0 KiB
TypeScript

import { Spreadsheet } from "../main"
export interface ViewportRect {
top: number
left: number
right: number
bottom: number
}
export class Scroller {
element: HTMLDivElement
private verticalScroller: HTMLDivElement
private horizontalScroller: HTMLDivElement
private root: Spreadsheet
constructor(root: Spreadsheet) {
this.root = root
const { horizontalScroller, scroller, verticalScroller } = this.buildComponent()
this.element = scroller
this.verticalScroller = verticalScroller
this.horizontalScroller = horizontalScroller
this.element.style.height = this.root.config.view.height + 'px'
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() {
const scroller = document.createElement('div')
const verticalScroller = document.createElement('div')
const horizontalScroller = document.createElement('div')
const groupScrollers = document.createElement('div')
const stack = document.createElement('div')
verticalScroller.style.width = '0px'
verticalScroller.style.pointerEvents = 'none'
horizontalScroller.style.pointerEvents = 'none'
groupScrollers.style.display = 'flex'
stack.appendChild(verticalScroller)
stack.appendChild(horizontalScroller)
groupScrollers.appendChild(stack)
this.verticalScroller = verticalScroller
this.horizontalScroller = horizontalScroller
scroller.appendChild(groupScrollers)
scroller.classList.add('scroller')
return { scroller, verticalScroller, horizontalScroller }
}
getActualHeight() {
return this.root.config.rows.reduce((acc, curr) => {
acc += curr.height
return acc
}, 0)
}
getActualWidth() {
return this.root.config.columns.reduce((acc, curr) => {
acc += curr.width
return acc
}, 0)
}
updateScrollerSize() {
const totalHeight = this.getActualHeight()
const totalWidth = this.getActualWidth()
this.setScrollerHeight(totalHeight)
this.setScrollerWidth(totalWidth)
}
setScrollerHeight(height: number) {
this.verticalScroller.style.height = height + 'px'
}
setScrollerWidth(width: number) {
this.horizontalScroller.style.width = width + 'px'
}
}