Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core | Container: Refactoring and pre-render step #265

Merged
merged 1 commit into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions packages/ts/src/containers/single-container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class SingleContainer<Data> extends ContainerCore {

public updateContainer (containerConfig: SingleContainerConfigInterface<Data>, preventRender?: boolean): void {
super.updateContainer(containerConfig)
this.removeAllChildren()
this._removeAllChildren()

this.component = containerConfig.component
if (containerConfig.sizing) this.component.sizing = containerConfig.sizing
Expand Down Expand Up @@ -86,11 +86,15 @@ export class SingleContainer<Data> extends ContainerCore {
return this.width / componentWidth
}

_render (duration?: number): void {
protected _preRender (): void {
super._preRender()
this.component.setSize(this.width, this.height, this.containerWidth, this.containerHeight)
}

protected _render (duration?: number): void {
const { config, component } = this
super._render(duration)

component.setSize(this.width, this.height, this.containerWidth, this.containerHeight)
component.g.attr('transform', `translate(${config.margin.left},${config.margin.top})`)
component.render(duration)

Expand All @@ -99,7 +103,7 @@ export class SingleContainer<Data> extends ContainerCore {

// Re-defining the `render()` function to handle different sizing techniques (`Sizing.Extend` and `Sizing.FitWidth`)
// Not calling `super.render()` because we don't want it to interfere with setting the SVG size here.
render (duration = this.config.duration): void {
public render (duration = this.config.duration): void {
const { config, component } = this

if (config.sizing === Sizing.Extend || config.sizing === Sizing.FitWidth) {
Expand Down Expand Up @@ -133,11 +137,12 @@ export class SingleContainer<Data> extends ContainerCore {
// Schedule the actual rendering in the next frame
cancelAnimationFrame(this._requestedAnimationFrame)
this._requestedAnimationFrame = requestAnimationFrame(() => {
this._preRender()
this._render(duration)
})
}

_onResize (): void {
protected _onResize (): void {
const { config } = this
super._onResize()
config.tooltip?.hide()
Expand Down
39 changes: 22 additions & 17 deletions packages/ts/src/containers/xy-container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class XYContainer<Datum> extends ContainerCore {
return clamp(this.containerHeight - margin.top - margin.bottom, 0, Number.POSITIVE_INFINITY)
}

setData (data: Datum[], preventRender?: boolean): void {
public setData (data: Datum[], preventRender?: boolean): void {
const { components, config } = this
if (!data) return
this.datamodel.data = data
Expand All @@ -129,9 +129,9 @@ export class XYContainer<Datum> extends ContainerCore {
if (!preventRender) this.render()
}

updateContainer (containerConfig: XYContainerConfigInterface<Datum>, preventRender?: boolean): void {
public updateContainer (containerConfig: XYContainerConfigInterface<Datum>, preventRender?: boolean): void {
super.updateContainer(containerConfig)
this.removeAllChildren()
this._removeAllChildren()

// If there were any new components added we need to pass them data
this.setData(this.datamodel.data, true)
Expand Down Expand Up @@ -177,7 +177,7 @@ export class XYContainer<Datum> extends ContainerCore {
if (!preventRender) this.render()
}

updateComponents (componentConfigs: XYConfigInterface<Datum>[], preventRender?: boolean): void {
public updateComponents (componentConfigs: XYConfigInterface<Datum>[], preventRender?: boolean): void {
const { config } = this

this.components.forEach((c, i) => {
Expand All @@ -187,32 +187,37 @@ export class XYContainer<Datum> extends ContainerCore {
}
})

this.updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair)
this._updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair)
if (!preventRender) this.render()
}

update (containerConfig: XYContainerConfigInterface<Datum>, componentConfigs?: XYComponentConfigInterface<Datum>[], data?: Datum[]): void {
public update (containerConfig: XYContainerConfigInterface<Datum>, componentConfigs?: XYComponentConfigInterface<Datum>[], data?: Datum[]): void {
if (data) this.datamodel.data = data // Just updating the data model because the `updateContainer` method has the `setData` step inside
if (containerConfig) this.updateContainer(containerConfig, true)
if (componentConfigs) this.updateComponents(componentConfigs, true)
this.render()
}

_render (customDuration?: number): void {
protected _preRender (): void {
const { config } = this
super._render()
super._preRender()

// Calculate extra margin required to fit the axes
if (config.autoMargin) {
this._setAutoMargin()
}

// Update Scales of all the components at once to calculate required paddings and sync them
this._updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair)
}

protected _render (customDuration?: number): void {
const { config } = this
super._render()

// Get chart total margin after auto margin calculations
const margin = this._getMargin()

// Update Scales of all the components at once to calculate required paddings and sync them
this.updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair)

// Render components
for (const c of this.components) {
c.g.attr('transform', `translate(${margin.left},${margin.top})`)
Expand Down Expand Up @@ -261,14 +266,14 @@ export class XYContainer<Datum> extends ContainerCore {
this._firstRender = false
}

updateScales<T extends XYComponentCore<Datum>> (...components: T[]): void {
private _updateScales<T extends XYComponentCore<Datum>> (...components: T[]): void {
const c = clean(components || this.components)
this._setScales(...c)
this._updateScalesDomain(...c)
this._updateScalesRange(...c)
}

_setScales<T extends XYComponentCore<Datum>> (...components: T[]): void {
private _setScales<T extends XYComponentCore<Datum>> (...components: T[]): void {
const { config } = this
if (!components) return

Expand All @@ -277,7 +282,7 @@ export class XYContainer<Datum> extends ContainerCore {
if (config.yScale) components.forEach(c => c.setScale(ScaleDimension.Y, config.yScale))
}

_updateScalesDomain<T extends XYComponentCore<Datum>> (...components: T[]): void {
private _updateScalesDomain<T extends XYComponentCore<Datum>> (...components: T[]): void {
const { config } = this
if (!components) return

Expand Down Expand Up @@ -309,7 +314,7 @@ export class XYContainer<Datum> extends ContainerCore {
})
}

_updateScalesRange<T extends XYComponentCore<Datum>> (...components: T[]): void {
private _updateScalesRange<T extends XYComponentCore<Datum>> (...components: T[]): void {
const { config } = this
if (!components) return

Expand Down Expand Up @@ -345,7 +350,7 @@ export class XYContainer<Datum> extends ContainerCore {
}
}

_renderAxes (duration: number): void {
private _renderAxes (duration: number): void {
const { config: { xAxis, yAxis } } = this
const margin = this._getMargin()

Expand All @@ -357,7 +362,7 @@ export class XYContainer<Datum> extends ContainerCore {
})
}

_setAutoMargin (): void {
private _setAutoMargin (): void {
const { config: { xAxis, yAxis } } = this

// At first we need to set the domain to the scales
Expand Down
21 changes: 14 additions & 7 deletions packages/ts/src/core/container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,20 @@ export class ContainerCore {
this.element = this.svg.node()
}

updateContainer<T extends ContainerConfigInterface> (config: T): void {
public updateContainer<T extends ContainerConfigInterface> (config: T): void {
// eslint-disable-next-line @typescript-eslint/naming-convention
const ConfigModel = (this.config.constructor as typeof ContainerConfig)
this.prevConfig = this.config
this.config = new ConfigModel().init(config)
}

_render (duration?: number): void {
// The `_preRender` step should be used to perform some actions before rendering.
// For example, calculating scales, setting component sizes, etc ...
// eslint-disable-next-line @typescript-eslint/no-empty-function
protected _preRender (): void {}

// The `_render` step should be used to perform the actual rendering
protected _render (duration?: number): void {
const { config } = this

// Add `svgDefs` if provided in the config
Expand All @@ -70,7 +76,7 @@ export class ContainerCore {

// Warning: Some Containers (i.e. Single Container) may override this method, so if you introduce any changes here,
// make sure to check that other containers didn't break after them.
render (duration = this.config.duration): void {
public render (duration = this.config.duration): void {
const width = this.config.width || this.containerWidth
const height = this.config.height || this.containerHeight

Expand All @@ -88,6 +94,7 @@ export class ContainerCore {
// Schedule the actual rendering in the next frame
cancelAnimationFrame(this._requestedAnimationFrame)
this._requestedAnimationFrame = requestAnimationFrame(() => {
this._preRender()
this._render(duration)
})
}
Expand All @@ -112,19 +119,19 @@ export class ContainerCore {
return clamp(this.containerHeight - this.config.margin.top - this.config.margin.bottom, 0, Number.POSITIVE_INFINITY)
}

removeAllChildren (): void {
protected _removeAllChildren (): void {
while (this.element.firstChild) {
this.element.removeChild(this.element.firstChild)
}
}

_onResize (): void {
protected _onResize (): void {
const { config } = this
const redrawOnResize = config.sizing === Sizing.Fit || config.sizing === Sizing.FitWidth
if (redrawOnResize) this.render(0)
}

_setUpResizeObserver (): void {
protected _setUpResizeObserver (): void {
if (this._resizeObserver) return
const containerRect = this._container.getBoundingClientRect()
this._containerSize = { width: containerRect.width, height: containerRect.height }
Expand All @@ -143,7 +150,7 @@ export class ContainerCore {
this._resizeObserver.observe(this._container)
}

destroy (): void {
public destroy (): void {
cancelAnimationFrame(this._requestedAnimationFrame)
this._resizeObserver?.disconnect()
this.svg.remove()
Expand Down