Skip to content

Commit

Permalink
impr: design improvements, adding custom layouts. #245
Browse files Browse the repository at this point in the history
  • Loading branch information
liihuu committed Nov 9, 2023
1 parent 018d3eb commit 5703eeb
Show file tree
Hide file tree
Showing 33 changed files with 731 additions and 495 deletions.
276 changes: 206 additions & 70 deletions src/Chart.ts

Large diffs are not rendered by default.

95 changes: 49 additions & 46 deletions src/Event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ import { requestAnimationFrame, cancelAnimationFrame } from './common/utils/comp

import { AxisExtremum } from './component/Axis'
import YAxis from './component/YAxis'
import XAxis from './component/XAxis'

import Chart from './Chart'
import Pane, { PaneIdConstants } from './pane/Pane'
import Widget, { WidgetNameConstants } from './widget/Widget'
import { REAL_SEPARATOR_HEIGHT } from './widget/SeparatorWidget'
import Pane from './pane/Pane'
import { PaneIdConstants } from './pane/types'
import Widget from './widget/Widget'
import { WidgetNameConstants, REAL_SEPARATOR_HEIGHT } from './widget/types'
import DrawPane from './pane/DrawPane'

interface EventTriggerWidgetInfo {
pane: Nullable<Pane>
Expand Down Expand Up @@ -113,7 +116,7 @@ export default class Event implements EventHandler {

pinchEvent (e: MouseTouchEvent, scale: number): boolean {
const { pane, widget } = this._findWidgetByEvent(e)
if (pane?.getId() !== PaneIdConstants.XAXIS && widget?.getName() === WidgetNameConstants.MAIN) {
if (pane?.getId() !== PaneIdConstants.X_AXIS && widget?.getName() === WidgetNameConstants.MAIN) {
const event = this._makeWidgetEvent(e, widget)
const zoomScale = (scale - this._pinchScale) * 5
this._pinchScale = scale
Expand All @@ -137,10 +140,10 @@ export default class Event implements EventHandler {
let zoomCoordinate: Nullable<Coordinate> = null
const name = widget?.getName()
if (isTouch) {
if (name === WidgetNameConstants.MAIN || name === WidgetNameConstants.XAXIS) {
if (name === WidgetNameConstants.MAIN || name === WidgetNameConstants.X_AXIS) {
zoomCoordinate = { x: event.x, y: event.y }
} else {
const bounding = this._chart.getPaneById(PaneIdConstants.CANDLE)?.getBounding() as Bounding
const bounding = this._chart.getDrawPaneById(PaneIdConstants.CANDLE)?.getBounding() as Bounding
zoomCoordinate = { x: bounding.width / 2, y: bounding.height / 2 }
}
} else {
Expand All @@ -166,13 +169,13 @@ export default class Event implements EventHandler {
return widget.dispatchEvent('mouseDownEvent', event)
}
case WidgetNameConstants.MAIN: {
const extremum = pane?.getAxisComponent().getExtremum() ?? null
const extremum = (pane as DrawPane<YAxis>).getAxisComponent().getExtremum() ?? null
this._prevYAxisExtremum = extremum === null ? extremum : { ...extremum }
this._startScrollCoordinate = { x: event.x, y: event.y }
this._chart.getChartStore().getTimeScaleStore().startScroll()
return widget.dispatchEvent('mouseDownEvent', event)
}
case WidgetNameConstants.XAXIS: {
case WidgetNameConstants.X_AXIS: {
const consumed = widget.dispatchEvent('mouseDownEvent', event)
if (consumed) {
this._chart.updatePane(UpdateLevel.Overlay)
Expand All @@ -181,12 +184,12 @@ export default class Event implements EventHandler {
this._xAxisStartScaleDistance = event.pageX
return consumed
}
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.Y_AXIS: {
const consumed = widget.dispatchEvent('mouseDownEvent', event)
if (consumed) {
this._chart.updatePane(UpdateLevel.Overlay)
}
const extremum = pane?.getAxisComponent().getExtremum() ?? null
const extremum = (pane as DrawPane<YAxis>).getAxisComponent().getExtremum() ?? null
this._prevYAxisExtremum = extremum === null ? extremum : { ...extremum }
this._yAxisStartScaleDistance = event.pageY
return consumed
Expand Down Expand Up @@ -224,8 +227,8 @@ export default class Event implements EventHandler {
return consumed
}
case WidgetNameConstants.SEPARATOR:
case WidgetNameConstants.XAXIS:
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.X_AXIS:
case WidgetNameConstants.Y_AXIS: {
const consumed = widget.dispatchEvent('mouseMoveEvent', event)
this._chart.getChartStore().getTooltipStore().setCrosshair()
return consumed
Expand All @@ -252,7 +255,7 @@ export default class Event implements EventHandler {
const bounding = widget.getBounding()
const consumed = widget.dispatchEvent('pressedMouseMoveEvent', event)
if (!consumed && this._startScrollCoordinate !== null) {
const yAxis = pane?.getAxisComponent() as YAxis
const yAxis = (pane as DrawPane<YAxis>).getAxisComponent()
if (this._prevYAxisExtremum !== null && !yAxis.getAutoCalcTickFlag() && yAxis.getScrollZoomEnabled()) {
const { min, max, range } = this._prevYAxisExtremum
let distance: number
Expand Down Expand Up @@ -282,10 +285,10 @@ export default class Event implements EventHandler {
this._chart.getChartStore().getTooltipStore().setCrosshair({ x: event.x, y: event.y, paneId: pane?.getId() })
return consumed
}
case WidgetNameConstants.XAXIS: {
case WidgetNameConstants.X_AXIS: {
const consumed = widget.dispatchEvent('pressedMouseMoveEvent', event)
if (!consumed) {
const xAxis = pane?.getAxisComponent()
const xAxis = (pane as DrawPane<XAxis>).getAxisComponent()
if (xAxis?.getScrollZoomEnabled() ?? true) {
const scale = this._xAxisStartScaleDistance / event.pageX
const zoomScale = (scale - this._xAxisScale) * 10
Expand All @@ -297,18 +300,17 @@ export default class Event implements EventHandler {
}
return consumed
}
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.Y_AXIS: {
const consumed = widget.dispatchEvent('pressedMouseMoveEvent', event)
if (!consumed) {
const yAxis = pane?.getAxisComponent() as YAxis
const yAxis = (pane as DrawPane<YAxis>).getAxisComponent()
if (this._prevYAxisExtremum !== null && yAxis.getScrollZoomEnabled()) {
const { min, max, range } = this._prevYAxisExtremum
const scale = event.pageY / this._yAxisStartScaleDistance
const newRange = range * scale
const difRange = (newRange - range) / 2
const newMin = min - difRange
const newMax = max + difRange
const yAxis = pane?.getAxisComponent() as YAxis
const newRealMin = yAxis.convertToRealValue(newMin)
const newRealMax = yAxis.convertToRealValue(newMax)
yAxis.setExtremum({
Expand Down Expand Up @@ -340,8 +342,8 @@ export default class Event implements EventHandler {
switch (name) {
case WidgetNameConstants.MAIN:
case WidgetNameConstants.SEPARATOR:
case WidgetNameConstants.XAXIS:
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.X_AXIS:
case WidgetNameConstants.Y_AXIS: {
consumed = widget.dispatchEvent('mouseUpEvent', event)
break
}
Expand Down Expand Up @@ -377,8 +379,8 @@ export default class Event implements EventHandler {
const name = widget.getName()
switch (name) {
case WidgetNameConstants.MAIN:
case WidgetNameConstants.XAXIS:
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.X_AXIS:
case WidgetNameConstants.Y_AXIS: {
consumed = widget.dispatchEvent('mouseRightClickEvent', event)
break
}
Expand All @@ -399,8 +401,8 @@ export default class Event implements EventHandler {
const event = this._makeWidgetEvent(e, widget)
return widget.dispatchEvent('mouseDoubleClickEvent', event)
}
case WidgetNameConstants.YAXIS: {
const yAxis = pane?.getAxisComponent() as YAxis
case WidgetNameConstants.Y_AXIS: {
const yAxis = (pane as DrawPane<YAxis>).getAxisComponent()
if (!yAxis.getAutoCalcTickFlag()) {
yAxis.setAutoCalcTickFlag(true)
this._chart.adjustPaneViewport(false, true, true, true)
Expand Down Expand Up @@ -457,8 +459,8 @@ export default class Event implements EventHandler {
}
return true
}
case WidgetNameConstants.XAXIS:
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.X_AXIS:
case WidgetNameConstants.Y_AXIS: {
const consumed = widget.dispatchEvent('mouseDownEvent', event)
if (consumed) {
this._chart.updatePane(UpdateLevel.Overlay)
Expand Down Expand Up @@ -499,8 +501,8 @@ export default class Event implements EventHandler {
}
return true
}
case WidgetNameConstants.XAXIS:
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.X_AXIS:
case WidgetNameConstants.Y_AXIS: {
const consumed = widget.dispatchEvent('pressedMouseMoveEvent', event)
if (consumed) {
event.preventDefault?.()
Expand Down Expand Up @@ -547,8 +549,8 @@ export default class Event implements EventHandler {
}
return true
}
case WidgetNameConstants.XAXIS:
case WidgetNameConstants.YAXIS: {
case WidgetNameConstants.X_AXIS:
case WidgetNameConstants.Y_AXIS: {
const consumed = widget.dispatchEvent('mouseUpEvent', event)
if (consumed) {
this._chart.updatePane(UpdateLevel.Overlay)
Expand Down Expand Up @@ -606,10 +608,24 @@ export default class Event implements EventHandler {
}

private _findWidgetByEvent (event: MouseTouchEvent): EventTriggerWidgetInfo {
const panes = this._chart.getAllPanes()
const { x, y } = event
let pane: Nullable<Pane> = null
for (const [, p] of panes) {
const separatorPanes = this._chart.getAllSeparatorPanes()
const separatorSize = this._chart.getChartStore().getStyles().separator.size
for (const [, pane] of separatorPanes) {
const bounding = pane.getBounding()
const top = bounding.top - Math.round((REAL_SEPARATOR_HEIGHT - separatorSize) / 2)
if (
x >= bounding.left && x <= bounding.left + bounding.width &&
y >= top && y <= top + REAL_SEPARATOR_HEIGHT
) {
return { pane, widget: pane.getWidget() }
}
}

const drawPanes = this._chart.getAllDrawPanes()

let pane: Nullable<DrawPane> = null
for (const [, p] of drawPanes) {
const bounding = p.getBounding()
if (
x >= bounding.left && x <= bounding.left + bounding.width &&
Expand All @@ -619,21 +635,8 @@ export default class Event implements EventHandler {
break
}
}
if (pane === null) {
pane = this._chart.getPaneById(PaneIdConstants.XAXIS)
}
let widget: Nullable<Widget> = null
if (pane !== null) {
const separatorWidget = pane.getSeparatorWidget()
if (separatorWidget !== null) {
const separatorBounding = separatorWidget.getBounding()
if (
x >= separatorBounding.left && x <= separatorBounding.left + separatorBounding.width &&
y >= separatorBounding.top && y <= (separatorBounding.top + REAL_SEPARATOR_HEIGHT)
) {
widget = separatorWidget
}
}
if (widget === null) {
const mainWidget = pane.getMainWidget()
const mainBounding = mainWidget.getBounding()
Expand Down
17 changes: 16 additions & 1 deletion src/Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
*/

import DeepPartial from './common/DeepPartial'

import { Styles } from './common/Styles'
import { formatDate, formatBigNumber } from './common/utils/format'

import { IndicatorCreate } from './component/Indicator'
import { PaneOptions } from './pane/types'

export enum FormatDateType {
Tooltip,
Crosshair,
Expand Down Expand Up @@ -53,7 +55,20 @@ export interface Locales {
[key: string]: string
}

export const enum LayoutChildType {
Candle = 'candle',
Indicator = 'indicator',
XAxis = 'xAxis'
}

export interface LayoutChild {
type: LayoutChildType
content?: Array<string | IndicatorCreate>
options?: PaneOptions
}

export interface Options {
layout?: LayoutChild[]
locale?: string
timezone?: string
styles?: string | DeepPartial<Styles>
Expand Down
10 changes: 6 additions & 4 deletions src/component/Axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* limitations under the License.
*/

import Pane from '../pane/Pane'
import DrawPane from '../pane/DrawPane'

import { getPrecision, nice, round } from '../common/utils/number'

Expand All @@ -37,19 +37,19 @@ export interface Axis {
}

export default abstract class AxisImp {
private readonly _parent: Pane<AxisImp>
private readonly _parent: DrawPane<AxisImp>

private _extremum: AxisExtremum = { min: 0, max: 0, range: 0, realMin: 0, realMax: 0, realRange: 0 }
private _prevExtremum: AxisExtremum = { min: 0, max: 0, range: 0, realMin: 0, realMax: 0, realRange: 0 }
private _ticks: AxisTick[] = []

private _autoCalcTickFlag = true

constructor (parent: Pane<AxisImp>) {
constructor (parent: DrawPane<AxisImp>) {
this._parent = parent
}

getParent (): Pane<AxisImp> { return this._parent }
getParent (): DrawPane<AxisImp> { return this._parent }

buildTicks (force: boolean): boolean {
if (this._autoCalcTickFlag) {
Expand Down Expand Up @@ -117,6 +117,8 @@ export default abstract class AxisImp {

protected abstract optimalTicks (ticks: AxisTick[]): AxisTick[]

abstract getAutoSize (): number

abstract convertToPixel (value: number): number
abstract convertFromPixel (px: number): number
}
2 changes: 1 addition & 1 deletion src/component/XAxis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export default class XAxisImp extends AxisImp {
return null
}

getAutoSize (): number {
override getAutoSize (): number {
const styles = this.getParent().getChart().getStyles()
const xAxisStyles = styles.xAxis
const height = xAxisStyles.size
Expand Down
2 changes: 1 addition & 1 deletion src/component/YAxis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ export default class YAxisImp extends AxisImp implements YAxis {
return optimalTicks
}

getAutoSize (): number {
override getAutoSize (): number {
const pane = this.getParent()
const chart = pane.getChart()
const styles = chart.getStyles()
Expand Down
14 changes: 5 additions & 9 deletions src/pane/CandlePane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,21 @@
* limitations under the License.
*/

import Nullable from '../common/Nullable'

import DrawWidget from '../widget/DrawWidget'
import CandleWidget from '../widget/CandleWidget'
import SeparatorWidget from '../widget/SeparatorWidget'

import DrawPane from './DrawPane'
import IndicatorPane from './IndicatorPane'
import YAxis from '../component/YAxis'

import { PaneNameConstants } from './types'

export default class CandlePane extends IndicatorPane {
override getName (): string {
return 'candle'
return PaneNameConstants.CANDLE
}

override createMainWidget (container: HTMLElement): DrawWidget<YAxis> {
override createMainWidget (container: HTMLElement): DrawWidget<DrawPane<YAxis>> {
return new CandleWidget(container, this)
}

override createSeparatorWidget (): Nullable<SeparatorWidget> {
return null
}
}
Loading

0 comments on commit 5703eeb

Please sign in to comment.