From 7ca321369e086090205140bb53db7a148e5db281 Mon Sep 17 00:00:00 2001 From: mawsyh Date: Mon, 14 Aug 2023 15:36:26 +0330 Subject: [PATCH 1/2] rectText figure width corrected --- src/extension/figure/rectText.ts | 1 + src/extension/figure/text.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/extension/figure/rectText.ts b/src/extension/figure/rectText.ts index 5e1ab24ca..730174418 100644 --- a/src/extension/figure/rectText.ts +++ b/src/extension/figure/rectText.ts @@ -33,6 +33,7 @@ export function drawRectText (ctx: CanvasRenderingContext2D, attrs: TextAttrs, s } = styles ctx.font = createFont(size, weight, family) const textWidth = ctx.measureText(text).width + attrs.textWidth = textWidth const rect = getTextRect(attrs, styles, textWidth) drawRect(ctx, rect, { ...styles, color: styles.backgroundColor }) drawText(ctx, { x: rect.x + paddingLeft, y: rect.y + paddingTop, text, align: 'left', baseline: 'top' }, styles) diff --git a/src/extension/figure/text.ts b/src/extension/figure/text.ts index c310fa557..1d0550157 100644 --- a/src/extension/figure/text.ts +++ b/src/extension/figure/text.ts @@ -25,7 +25,7 @@ export function getTextRect (attrs: TextAttrs, styles: Partial, t const { size = 12, paddingLeft = 0, paddingTop = 0, paddingRight = 0, paddingBottom = 0 } = styles const { x, y, text, align = 'left', baseline = 'top' } = attrs const length = text.length - textWidth = textWidth ?? size * length + textWidth = attrs?.textWidth ?? (textWidth ?? size * length) const textHeight = size let startX: number switch (align) { @@ -96,6 +96,7 @@ export interface TextAttrs { text: string align?: CanvasTextAlign baseline?: CanvasTextBaseline + textWidth?: number } const text: FigureTemplate> = { From 3d70972f7290a15afd238605c20ec2d604d24022 Mon Sep 17 00:00:00 2001 From: liihuu Date: Sun, 20 Aug 2023 04:26:36 +0800 Subject: [PATCH 2/2] feat: figure `text` add attrs `width` and `height` opt: merge `rectText` and `text` Co-authored-by: mawsyh --- docs/en-US/guide/chart-api.md | 44 +++------- docs/en-US/guide/datasource.md | 1 - docs/en-US/guide/figure.md | 37 ++------- docs/guide/chart-api.md | 42 ++-------- docs/guide/datasource.md | 1 - docs/guide/figure.md | 41 +++------- src/common/Options.ts | 97 +++++++++++++---------- src/common/utils/color.ts | 3 + src/component/Indicator.ts | 6 +- src/component/Overlay.ts | 13 +-- src/extension/figure/rect.ts | 35 +++++--- src/extension/figure/rectText.ts | 45 +++-------- src/extension/figure/text.ts | 51 +++++++----- src/extension/overlay/index.ts | 10 ++- src/extension/overlay/simpleAnnotation.ts | 16 +++- src/extension/overlay/simpleTag.ts | 14 +++- src/index.ts | 4 +- src/store/OverlayStore.ts | 4 +- src/view/CandleLastPriceLabelView.ts | 2 +- src/view/CrosshairHorizontalLabelView.ts | 6 +- src/view/IndicatorLastValueView.ts | 2 +- src/view/IndicatorTooltipView.ts | 10 +-- src/view/OverlayView.ts | 10 +-- src/view/OverlayXAxisView.ts | 2 +- src/view/OverlayYAxisView.ts | 2 +- 25 files changed, 223 insertions(+), 275 deletions(-) create mode 100644 src/common/utils/color.ts diff --git a/docs/en-US/guide/chart-api.md b/docs/en-US/guide/chart-api.md index b10187ebc..f4b91045a 100644 --- a/docs/en-US/guide/chart-api.md +++ b/docs/en-US/guide/chart-api.md @@ -760,39 +760,6 @@ Draw a rectangle. - `borderRadius` border radius -### utils.drawText(ctx, text, styles) -```typescript -( - ctx: CanvasRenderingContext2D, - text: { - x: number - y: number - text: any - align?: 'center' | 'end' | 'left' | 'right' | 'start' - baseline?: 'alphabetic' | 'bottom' | 'hanging' | 'ideographic' | 'middle' | 'top' - }, - styles: { - color?: string - size?: number - family?: string - weight?: number | string - } -) => void -``` -Draw text. -- `ctx` canvas context -- `text` text parameter - - `x` starting point x-axis value - - `y` starting point y-axis value - - `text` text content - - `align` horizontal alignment - - `baseline` vertical alignment -- `styles` styles - - `color` color - - `size` size - - `family` font - - `weight` weight - ### utils.drawRectText(ctx, rectText, styles) ```typescript ( @@ -801,6 +768,8 @@ Draw text. x: number y: number text: any + width?: number + height?: number align?: 'center' | 'end' | 'left' | 'right' | 'start' baseline?: 'alphabetic' | 'bottom' | 'hanging' | 'ideographic' | 'middle' | 'top' }, @@ -823,12 +792,14 @@ Draw text. } ) => void ``` -Draw text with background. +Draw text. - `ctx` canvas context - `rectText` text parameter - `x` starting point x-axis value - `y` starting point y-axis value - `text` text content + - `width` width + - `height` height - `align` horizontal alignment - `baseline` vertical alignment - `styles` styles @@ -846,4 +817,7 @@ Draw text with background. - `borderStyle` border style - `borderRadius` border radius size - `borderDashedValue` border dashed line parameter value - - `backgroundColor` background color \ No newline at end of file + - `backgroundColor` background color + +### utils.drawRectText(ctx, rectText, styles) +Same as `utils.drawRectText(ctx, text, styles)`, it is deprecated and will be deleted after v10. Please use `utils.drawRectText(ctx, text, styles)` instead. \ No newline at end of file diff --git a/docs/en-US/guide/datasource.md b/docs/en-US/guide/datasource.md index 37513d15e..3de029e3c 100644 --- a/docs/en-US/guide/datasource.md +++ b/docs/en-US/guide/datasource.md @@ -20,4 +20,3 @@ The data required for the chart must be in a fixed format. Through the chart API turnover: number } ``` -``` diff --git a/docs/en-US/guide/figure.md b/docs/en-US/guide/figure.md index 4a4bcf52a..ddefdc9a3 100644 --- a/docs/en-US/guide/figure.md +++ b/docs/en-US/guide/figure.md @@ -165,34 +165,10 @@ new ({ x: number // The y-axis coordinate value of the starting point y: number - // text content - text: any - // alignment - align: CanvasTextAlign - // benchmark - baseline: CanvasTextBaseline - }, - styles: { - // color - color?: string - // size - size?: number - // font - family?: string - // thickness - weight?: string | number - } -}) => Figure -``` - -### rectText -```typescript -new ({ - attrs: { - // The x-axis coordinate value of the starting point - x: number - // The y-axis coordinate value of the starting point - y: number + // Fixed width + width: number + // Fixed height + height: number // text content text: any // alignment @@ -218,7 +194,7 @@ new ({ // top padding paddingTop?: number // Bottom padding - paddingBootom?: number + paddingBottom?: number // border style borderStyle?: 'solid' | 'dashed' // border color @@ -235,6 +211,9 @@ new ({ }) => Figure ``` +### rectText +Same as `text`, it is deprecated and will be deleted after v10. Please use `text` instead. + ## Customize figure To create a custom figure, you only need to generate the figure information, and then add it globally through `klinecharts.registerFigure`, and add it to the chart to use it like the built-in figures. diff --git a/docs/guide/chart-api.md b/docs/guide/chart-api.md index de4ad38ba..6ea44b57d 100644 --- a/docs/guide/chart-api.md +++ b/docs/guide/chart-api.md @@ -772,39 +772,8 @@ x: number y: number text: any - align?: 'center' | 'end' | 'left' | 'right' | 'start' - baseline?: 'alphabetic' | 'bottom' | 'hanging' | 'ideographic' | 'middle' | 'top' - }, - styles: { - color?: string - size?: number - family?: string - weight?: number | string - } -) => void -``` -绘制文字。 -- `ctx` 画布上下文 -- `text` 文字参数 - - `x` 起始点x轴值 - - `y` 起始点y轴值 - - `text` 文字内容 - - `align` 水平对齐方式 - - `baseline` 垂直对齐方式 -- `styles` 样式 - - `color` 颜色 - - `size` 尺寸 - - `family` 字体 - - `weight` 权重 - -### utils.drawRectText(ctx, rectText, styles) -```typescript -( - ctx: CanvasRenderingContext2D, - rectText: { - x: number - y: number - text: any + width?: number + height?: number align?: 'center' | 'end' | 'left' | 'right' | 'start' baseline?: 'alphabetic' | 'bottom' | 'hanging' | 'ideographic' | 'middle' | 'top' }, @@ -829,10 +798,12 @@ ``` 绘制带背景的文字。 - `ctx` 画布上下文 -- `rectText` 文字参数 +- `attrs` 文字参数 - `x` 起始点x轴值 - `y` 起始点y轴值 - `text` 文字内容 + - `width` 宽度 + - `height` 高度 - `align` 水平对齐方式 - `baseline` 垂直对齐方式 - `styles` 样式 @@ -851,3 +822,6 @@ - `borderRadius` 边框圆角尺寸 - `borderDashedValue` 边框虚线参数值 - `backgroundColor` 背景色 + +### utils.drawRectText(ctx, rectText, styles) +同`utils.drawText(ctx, text, styles)`,已废弃,v10之后会删除,请用`utils.drawText(ctx, text, styles)`代替。 \ No newline at end of file diff --git a/docs/guide/datasource.md b/docs/guide/datasource.md index 13d392b52..9efef0e6d 100644 --- a/docs/guide/datasource.md +++ b/docs/guide/datasource.md @@ -17,7 +17,6 @@ volume: number // 成交额,非必须字段,如果需要展示技术指标'EMV'和'AVP',则需要为该字段填充数据。 turnover: number - } ``` diff --git a/docs/guide/figure.md b/docs/guide/figure.md index 3c5eb959b..3847e98c5 100644 --- a/docs/guide/figure.md +++ b/docs/guide/figure.md @@ -167,38 +167,14 @@ new ({ y: number // 文字内容 text: any + // 指定宽 + width?: number + // 指定高 + height?: number // 对齐方式 - align: CanvasTextAlign + align?: CanvasTextAlign // 基准 - baseline: CanvasTextBaseline - }, - styles: { - // 颜色 - color?: string - // 尺寸 - size?: number - // 字体 - family?: string - // 粗细 - weight?: string | number - } -}) => Figure -``` - -### rectText -```typescript -new ({ - attrs: { - // 起始点x轴坐标值 - x: number - // 起始点y轴坐标值 - y: number - // 文字内容 - text: any - // 对齐方式 - align: CanvasTextAlign - // 基准 - baseline: CanvasTextBaseline + baseline?: CanvasTextBaseline }, styles: { // 样式,可选项`fill`,`stroke`,`stroke_fill` @@ -218,7 +194,7 @@ new ({ // 上内边距 paddingTop?: number // 下内边距 - paddingBootom?: number + paddingBottom?: number // 边框样式 borderStyle?: 'solid' | 'dashed' // 边框颜色 @@ -235,6 +211,9 @@ new ({ }) => Figure ``` +### rectText +同`text`,已废弃,v10之后会删除,请用`text`代替。 + ## 自定义基础图形 创建一个自定义基础图形,只需要生成基础图形信息,然后通过`klinecharts.registerFigure`全局添加,添加到图表即可和内置基础图形一样去使用。 diff --git a/src/common/Options.ts b/src/common/Options.ts index 0ad8b81be..9f87cf264 100644 --- a/src/common/Options.ts +++ b/src/common/Options.ts @@ -18,6 +18,20 @@ import KLineData from './KLineData' import { formatDate, formatBigNumber } from './utils/format' +export interface Margin { + marginLeft: number + marginTop: number + marginRight: number + marginBottom: number +} + +export interface Padding { + paddingLeft: number + paddingTop: number + paddingRight: number + paddingBottom: number +} + /** * line type */ @@ -60,23 +74,12 @@ export interface RectStyle extends PolygonStyle { borderRadius: number } -export interface TextStyle { +export interface TextStyle extends Padding { + style: PolygonType color: string size: number family: string weight: number | string -} - -export interface StateTextStyle extends TextStyle { - show: boolean -} - -export interface RectTextStyle extends TextStyle { - style: PolygonType - paddingLeft: number - paddingTop: number - paddingRight: number - paddingBottom: number borderStyle: LineType borderDashedValue: number[] borderSize: number @@ -85,18 +88,23 @@ export interface RectTextStyle extends TextStyle { backgroundColor: string } -export interface StateRectTextStyle extends RectTextStyle { +/** + * @deprecated + * Starting from v10, it will be deleted + */ +export type RectTextStyle = TextStyle + +export interface StateTextStyle extends TextStyle { show: boolean } -export interface MarginTextStyle extends StateTextStyle { - marginLeft: number - marginTop: number - marginRight: number - marginBottom: number -} +/** + * @deprecated + * Starting from v10, it will be deleted + */ +export type StateRectTextStyle = StateTextStyle -export type LastValueMarkTextStyle = Omit +export type LastValueMarkTextStyle = Omit export enum TooltipShowRule { Always = 'always', @@ -126,7 +134,7 @@ export interface GridStyle { vertical: StateLineStyle } -export type TooltipTextStyle = Omit +export type TooltipTextStyle = Pick & Margin export interface TooltipDataChild { text: string @@ -143,17 +151,9 @@ export enum TooltipIconPosition { Middle = 'middle', Right = 'right' } -export interface TooltipIconStyle { +export interface TooltipIconStyle extends Padding, Margin { id: string position: TooltipIconPosition - marginLeft: number - marginTop: number - marginRight: number - marginBottom: number - paddingLeft: number - paddingTop: number - paddingRight: number - paddingBottom: number color: string activeColor: string size: number @@ -226,12 +226,8 @@ export enum CandleTooltipRectPosition { Pointer = 'pointer' } -export interface CandleTooltipRectStyle extends Omit { +export interface CandleTooltipRectStyle extends Omit, Padding { position: CandleTooltipRectPosition - paddingLeft: number - paddingRight: number - paddingTop: number - paddingBottom: number offsetLeft: number offsetTop: number offsetRight: number @@ -344,8 +340,9 @@ function getDefaultCandleStyle (): CandleStyle { paddingTop: 4, paddingRight: 4, paddingBottom: 4, + borderColor: 'transparent', borderStyle: LineType.Solid, - borderSize: 1, + borderSize: 0, borderDashedValue: [2, 2], color: '#FFFFFF', family: 'Helvetica Neue', @@ -482,6 +479,7 @@ function getDefaultIndicatorStyle (): IndicatorStyle { family: 'Helvetica Neue', weight: 'normal', borderStyle: LineType.Solid, + borderColor: 'transparent', borderSize: 1, borderDashedValue: [2, 2], paddingLeft: 4, @@ -518,7 +516,7 @@ export interface AxisTickLineStyle extends AxisLineStyle { length: number } -export interface AxisTickTextStyle extends StateTextStyle { +export interface AxisTickTextStyle extends Pick { marginStart: number marginEnd: number } @@ -612,7 +610,7 @@ function getDefaultYAxisStyle (): YAxisStyle { export interface CrosshairDirectionStyle { show: boolean line: StateLineStyle - text: StateRectTextStyle + text: StateTextStyle } export interface CrosshairStyle { @@ -702,7 +700,11 @@ export interface OverlayStyle { circle: PolygonStyle arc: LineStyle text: TextStyle - rectText: RectTextStyle + /** + * @deprecated + * Starting from v10, it will be deleted + */ + rectText: TextStyle [key: string]: any } @@ -757,10 +759,21 @@ function getDefaultOverlayStyle (): OverlayStyle { dashedValue: [2, 2] }, text: { - color: '#1677FF', + style: PolygonType.Fill, + color: '#FFFFFF', size: 12, family: 'Helvetica Neue', - weight: 'normal' + weight: 'normal', + borderStyle: LineType.Solid, + borderDashedValue: [2, 2], + borderSize: 0, + borderRadius: 2, + borderColor: '#1677FF', + paddingLeft: 0, + paddingRight: 0, + paddingTop: 0, + paddingBottom: 0, + backgroundColor: 'transparent' }, rectText: { style: PolygonType.Fill, diff --git a/src/common/utils/color.ts b/src/common/utils/color.ts new file mode 100644 index 000000000..e04916ade --- /dev/null +++ b/src/common/utils/color.ts @@ -0,0 +1,3 @@ +export function transparent (color: string): boolean { + return color === 'transparent' +} diff --git a/src/component/Indicator.ts b/src/component/Indicator.ts index 3b32d06f6..8cd5105a8 100644 --- a/src/component/Indicator.ts +++ b/src/component/Indicator.ts @@ -76,7 +76,7 @@ export interface IndicatorFigure { styles?: IndicatorFigureStylesCallback } -export type IndicatorRegenerateFiguresCallback = (calcParms: any[]) => Array> +export type IndicatorRegenerateFiguresCallback = (calcParams: any[]) => Array> export interface IndicatorTooltipData { name: string @@ -205,9 +205,9 @@ export interface Indicator { result: D[] } -export type IndicatorTemplate = ExcludePickPartial, 'reult'>, 'name' | 'calc'> +export type IndicatorTemplate = ExcludePickPartial, 'result'>, 'name' | 'calc'> -export type IndicatorCreate = ExcludePickPartial, 'reult'>, 'name'> +export type IndicatorCreate = ExcludePickPartial, 'result'>, 'name'> export type IndicatorConstructor = new () => IndicatorImp diff --git a/src/component/Overlay.ts b/src/component/Overlay.ts index 4439bc458..27d3202c1 100644 --- a/src/component/Overlay.ts +++ b/src/component/Overlay.ts @@ -23,7 +23,7 @@ import Precision from '../common/Precision' import { OverlayStyle } from '../common/Options' import { MouseTouchEvent } from '../common/SyntheticEvent' -import { clone } from '../common/utils/typeChecks' +import { clone, merge } from '../common/utils/typeChecks' import TimeScaleStore from '../store/TimeScaleStore' @@ -281,7 +281,8 @@ export interface Overlay { export type OverlayTemplate = ExcludePickPartial, 'name'> export type OverlayCreate = ExcludePickPartial, 'name'> export type OverlayRemove = Partial> -export type OverlayConstructor = new () => OverlayImp +export type OverlayInnerConstructor = new () => OverlayImp +export type OverlayConstructor = new () => Overlay const OVERLAY_DRAW_STEP_START = 1 const OVERLAY_DRAW_STEP_FINISHED = -1 @@ -358,7 +359,7 @@ export default abstract class OverlayImp implements Overlay { this.mode = mode ?? OverlayMode.Normal this.modeSensitivity = modeSensitivity ?? 8 this.extendData = extendData - this.styles = styles ?? null + this.styles = styles ?? {} this.createPointFigures = createPointFigures ?? null this.createXAxisFigures = createXAxisFigures ?? null this.createYAxisFigures = createYAxisFigures ?? null @@ -417,8 +418,8 @@ export default abstract class OverlayImp implements Overlay { } setStyles (styles: Nullable>): boolean { - if (styles !== this.styles) { - this.styles = styles + if (styles !== null) { + merge(this.styles, styles) return true } return false @@ -708,7 +709,7 @@ export default abstract class OverlayImp implements Overlay { } } - static extend (template: OverlayTemplate): OverlayConstructor { + static extend (template: OverlayTemplate): OverlayInnerConstructor { class Custom extends OverlayImp { constructor () { super(template) diff --git a/src/extension/figure/rect.ts b/src/extension/figure/rect.ts index 2b582d1b9..798fda2c1 100644 --- a/src/extension/figure/rect.ts +++ b/src/extension/figure/rect.ts @@ -14,6 +14,8 @@ import Coordinate from '../../common/Coordinate' import { RectStyle, PolygonType, LineType } from '../../common/Options' +import { transparent } from '../../common/utils/color' +import { isString } from '../../common/utils/typeChecks' import { FigureTemplate, DEVIATION } from '../../component/Figure' @@ -43,25 +45,34 @@ export function drawRect (ctx: CanvasRenderingContext2D, attrs: RectAttrs, style const { x, y, width: w, height: h } = attrs const { style = PolygonType.Fill, - color = 'currentColor', + color = 'transparent', borderSize = 1, - borderColor = 'currentColor', + borderColor = 'transparent', borderStyle = LineType.Solid, borderRadius: r = 0, borderDashedValue = [2, 2] } = styles if (style === PolygonType.Fill || styles.style === PolygonType.StrokeFill) { - ctx.fillStyle = color - ctx.beginPath() - ctx.moveTo(x + r, y) - ctx.arcTo(x + w, y, x + w, y + h, r) - ctx.arcTo(x + w, y + h, x, y + h, r) - ctx.arcTo(x, y + h, x, y, r) - ctx.arcTo(x, y, x + w, y, r) - ctx.closePath() - ctx.fill() + let draw = true + if (isString(color)) { + draw = !transparent(color) + } + if (draw) { + ctx.fillStyle = color + ctx.beginPath() + ctx.moveTo(x + r, y) + ctx.arcTo(x + w, y, x + w, y + h, r) + ctx.arcTo(x + w, y + h, x, y + h, r) + ctx.arcTo(x, y + h, x, y, r) + ctx.arcTo(x, y, x + w, y, r) + ctx.closePath() + ctx.fill() + } } - if (style === PolygonType.Stroke || styles.style === PolygonType.StrokeFill) { + if ( + (style === PolygonType.Stroke || styles.style === PolygonType.StrokeFill) && + (!transparent(borderColor) && borderSize >= 0) + ) { ctx.strokeStyle = borderColor ctx.lineWidth = borderSize if (borderStyle === LineType.Dashed) { diff --git a/src/extension/figure/rectText.ts b/src/extension/figure/rectText.ts index 730174418..d9a6cef80 100644 --- a/src/extension/figure/rectText.ts +++ b/src/extension/figure/rectText.ts @@ -12,41 +12,20 @@ * limitations under the License. */ -import Coordinate from '../../common/Coordinate' -import { RectTextStyle } from '../../common/Options' +import text, { drawText } from './text' -import { createFont } from '../../common/utils/canvas' - -import { FigureTemplate } from '../../component/Figure' - -import { TextAttrs, getTextRect, drawText, checkCoordinateOnText } from './text' -import { drawRect } from './rect' +/** + * @deprecated + * Starting from v10, it will be deleted + */ +const rectText = text -export function drawRectText (ctx: CanvasRenderingContext2D, attrs: TextAttrs, styles: Partial): void { - const { text } = attrs - const { - size = 12, - family, - weight, - paddingLeft = 0, - paddingTop = 0 - } = styles - ctx.font = createFont(size, weight, family) - const textWidth = ctx.measureText(text).width - attrs.textWidth = textWidth - const rect = getTextRect(attrs, styles, textWidth) - drawRect(ctx, rect, { ...styles, color: styles.backgroundColor }) - drawText(ctx, { x: rect.x + paddingLeft, y: rect.y + paddingTop, text, align: 'left', baseline: 'top' }, styles) -} +const drawRectText = drawText -const rectText: FigureTemplate> = { - name: 'rectText', - checkEventOn: (coordinate: Coordinate, attrs: TextAttrs, styles: Partial) => { - return checkCoordinateOnText(coordinate, attrs, styles) - }, - draw: (ctx: CanvasRenderingContext2D, attrs: TextAttrs, styles: Partial) => { - drawRectText(ctx, attrs, styles) - } -} +/** + * @deprecated + * Starting from v10, it will be deleted + */ +export { drawRectText } export default rectText diff --git a/src/extension/figure/text.ts b/src/extension/figure/text.ts index 1d0550157..fd2b2b538 100644 --- a/src/extension/figure/text.ts +++ b/src/extension/figure/text.ts @@ -13,20 +13,19 @@ */ import Coordinate from '../../common/Coordinate' -import { TextStyle, RectTextStyle } from '../../common/Options' +import { TextStyle } from '../../common/Options' -import { createFont } from '../../common/utils/canvas' +import { createFont, calcTextWidth } from '../../common/utils/canvas' import { FigureTemplate } from '../../component/Figure' -import { RectAttrs } from './rect' +import { RectAttrs, drawRect } from './rect' -export function getTextRect (attrs: TextAttrs, styles: Partial, textWidth?: number): RectAttrs { - const { size = 12, paddingLeft = 0, paddingTop = 0, paddingRight = 0, paddingBottom = 0 } = styles - const { x, y, text, align = 'left', baseline = 'top' } = attrs - const length = text.length - textWidth = attrs?.textWidth ?? (textWidth ?? size * length) - const textHeight = size +export function getTextRect (attrs: TextAttrs, styles: Partial): RectAttrs { + const { size = 12, paddingLeft = 0, paddingTop = 0, paddingRight = 0, paddingBottom = 0, weight = 'normal', family } = styles + const { x, y, text, align = 'left', baseline = 'top', width: w, height: h } = attrs + const width = w ?? (paddingLeft + calcTextWidth(text, size, weight, family) + paddingRight) + const height = h ?? (paddingTop + size + paddingBottom) let startX: number switch (align) { case 'left': @@ -36,11 +35,11 @@ export function getTextRect (attrs: TextAttrs, styles: Partial, t } case 'right': case 'end': { - startX = x - paddingRight - textWidth - paddingLeft + startX = x - width break } default: { - startX = x - textWidth / 2 - paddingLeft + startX = x - width / 2 break } } @@ -54,18 +53,18 @@ export function getTextRect (attrs: TextAttrs, styles: Partial, t case 'bottom': case 'ideographic': case 'alphabetic': { - startY = y - textHeight - paddingTop - paddingBottom + startY = y - height break } default: { - startY = y - textHeight / 2 - paddingTop + startY = y - height / 2 break } } - return { x: startX, y: startY, width: paddingLeft + textWidth + paddingRight, height: paddingTop + textHeight + paddingBottom } + return { x: startX, y: startY, width, height } } -export function checkCoordinateOnText (coordinate: Coordinate, attrs: TextAttrs, styles: Partial): boolean { +export function checkCoordinateOnText (coordinate: Coordinate, attrs: TextAttrs, styles: Partial): boolean { const { x, y, width, height } = getTextRect(attrs, styles) return ( coordinate.x >= x && @@ -76,27 +75,35 @@ export function checkCoordinateOnText (coordinate: Coordinate, attrs: TextAttrs, } export function drawText (ctx: CanvasRenderingContext2D, attrs: TextAttrs, styles: Partial): void { - const { x, y, text, align = 'left', baseline = 'top' } = attrs + const { text } = attrs const { color = 'currentColor', size = 12, - family, weight + family, + weight, + paddingLeft = 0, + paddingTop = 0, + paddingRight = 0 } = styles - ctx.textAlign = align - ctx.textBaseline = baseline - ctx.font = createFont(size, weight, family) + const rect = getTextRect(attrs, styles) + + drawRect(ctx, rect, { ...styles, color: styles.backgroundColor }) + ctx.textAlign = 'left' + ctx.textBaseline = 'top' + ctx.font = createFont(size, weight, family) ctx.fillStyle = color - ctx.fillText(text, x, y) + ctx.fillText(text, rect.x + paddingTop, rect.y + paddingTop, rect.width - paddingLeft - paddingRight) } export interface TextAttrs { x: number y: number text: string + width?: number + height?: number align?: CanvasTextAlign baseline?: CanvasTextBaseline - textWidth?: number } const text: FigureTemplate> = { diff --git a/src/extension/overlay/index.ts b/src/extension/overlay/index.ts index 3a354bdb2..d3d1ba1f3 100644 --- a/src/extension/overlay/index.ts +++ b/src/extension/overlay/index.ts @@ -14,7 +14,7 @@ import Nullable from '../../common/Nullable' -import OverlayImp, { OverlayTemplate, OverlayConstructor } from '../../component/Overlay' +import OverlayImp, { OverlayTemplate, OverlayConstructor, OverlayInnerConstructor } from '../../component/Overlay' import fibonacciLine from './fibonacciLine' import horizontalRayLine from './horizontalRayLine' @@ -33,7 +33,7 @@ import verticalStraightLine from './verticalStraightLine' import simpleAnnotation from './simpleAnnotation' import simpleTag from './simpleTag' -const overlays: Record = {} +const overlays: Record = {} const extensions = [ fibonacciLine, horizontalRayLine, horizontalSegment, horizontalStraightLine, @@ -50,6 +50,10 @@ function registerOverlay (template: OverlayTemplate): void { overlays[template.name] = OverlayImp.extend(template) } +function getOverlayInnerClass (name: string): Nullable { + return overlays[name] ?? null +} + function getOverlayClass (name: string): Nullable { return overlays[name] ?? null } @@ -58,4 +62,4 @@ function getSupportedOverlays (): string[] { return Object.keys(overlays) } -export { registerOverlay, getOverlayClass, getSupportedOverlays } +export { registerOverlay, getOverlayClass, getOverlayInnerClass, getSupportedOverlays } diff --git a/src/extension/overlay/simpleAnnotation.ts b/src/extension/overlay/simpleAnnotation.ts index 3842dcf96..669c823d4 100644 --- a/src/extension/overlay/simpleAnnotation.ts +++ b/src/extension/overlay/simpleAnnotation.ts @@ -14,10 +14,24 @@ import { OverlayTemplate } from '../../component/Overlay' import { isFunction, isValid } from '../../common/utils/typeChecks' +import { LineType } from '../../common/Options' const simpleAnnotation: OverlayTemplate = { name: 'simpleAnnotation', totalStep: 2, + styles: { + text: { + borderSize: 1, + borderRadius: 2, + borderColor: '#1677FF', + paddingLeft: 4, + paddingRight: 4, + paddingTop: 4, + paddingBottom: 4, + backgroundColor: '#1677FF' + }, + line: { style: LineType.Dashed } + }, createPointFigures: ({ overlay, coordinates }) => { let text if (isValid(overlay.extendData)) { @@ -43,7 +57,7 @@ const simpleAnnotation: OverlayTemplate = { ignoreEvent: true }, { - type: 'rectText', + type: 'text', attrs: { x: startX, y: arrowEndY, text: text ?? '', align: 'center', baseline: 'bottom' }, ignoreEvent: true } diff --git a/src/extension/overlay/simpleTag.ts b/src/extension/overlay/simpleTag.ts index 5afafa33d..187136ea9 100644 --- a/src/extension/overlay/simpleTag.ts +++ b/src/extension/overlay/simpleTag.ts @@ -21,6 +21,18 @@ import { isFunction, isValid } from '../../common/utils/typeChecks' const simpleTag: OverlayTemplate = { name: 'simpleTag', totalStep: 2, + styles: { + text: { + borderSize: 1, + borderRadius: 2, + borderColor: '#1677FF', + paddingLeft: 4, + paddingRight: 4, + paddingTop: 4, + paddingBottom: 4, + backgroundColor: '#1677FF' + } + }, createPointFigures: ({ bounding, coordinates }) => { return { type: 'line', @@ -55,7 +67,7 @@ const simpleTag: OverlayTemplate = { if (!isValid(text) && overlay.points[0].value !== undefined) { text = formatPrecision(overlay.points[0].value, precision.price) } - return { type: 'rectText', attrs: { x, y: coordinates[0].y, text: text ?? '', align: textAlign, baseline: 'middle' } } + return { type: 'text', attrs: { x, y: coordinates[0].y, text: text ?? '', align: textAlign, baseline: 'middle' } } } } diff --git a/src/index.ts b/src/index.ts index cb633ae52..fd81c50db 100644 --- a/src/index.ts +++ b/src/index.ts @@ -104,7 +104,7 @@ function init (ds: HTMLElement | string, options?: Options): Nullable { } /** - * Destory chart instace + * Destroy chart instance * @param dcs */ function dispose (dcs: HTMLElement | Chart | string): void { @@ -164,7 +164,7 @@ export { version, init, dispose, registerFigure, getSupportedFigures, getFigureClass, registerIndicator, getSupportedIndicators, - registerOverlay, getOverlayClass, getSupportedOverlays, + registerOverlay, getSupportedOverlays, getOverlayClass, registerLocale, getSupportedLocales, registerStyles, utils, LineType, PolygonType, TooltipShowRule, TooltipShowType, TooltipIconPosition, diff --git a/src/store/OverlayStore.ts b/src/store/OverlayStore.ts index 11aa2c156..5bff86f75 100644 --- a/src/store/OverlayStore.ts +++ b/src/store/OverlayStore.ts @@ -20,7 +20,7 @@ import { createId } from '../common/utils/id' import OverlayImp, { OVERLAY_ID_PREFIX, OVERLAY_ACTIVE_Z_LEVEL, OverlayCreate, OverlayRemove } from '../component/Overlay' -import { getOverlayClass } from '../extension/overlay/index' +import { getOverlayInnerClass } from '../extension/overlay/index' import ChartStore from './ChartStore' @@ -216,7 +216,7 @@ export default class OverlayStore { const ids = overlays.map(overlay => { const id = overlay.id ?? createId(OVERLAY_ID_PREFIX) if (this.getInstanceById(id) === null) { - const OverlayClazz = getOverlayClass(overlay.name) + const OverlayClazz = getOverlayInnerClass(overlay.name) if (OverlayClazz !== null) { const instance = new OverlayClazz() const count = (this._counter.get(paneId) ?? 0) + 1 diff --git a/src/view/CandleLastPriceLabelView.ts b/src/view/CandleLastPriceLabelView.ts index 7bb815390..e81b2bdd0 100644 --- a/src/view/CandleLastPriceLabelView.ts +++ b/src/view/CandleLastPriceLabelView.ts @@ -65,7 +65,7 @@ export default class CandleLastPriceLabelView extends View { textAlgin = 'right' } this.createFigure( - 'rectText', + 'text', { x, y: priceY, diff --git a/src/view/CrosshairHorizontalLabelView.ts b/src/view/CrosshairHorizontalLabelView.ts index 53db37807..d59de8f73 100644 --- a/src/view/CrosshairHorizontalLabelView.ts +++ b/src/view/CrosshairHorizontalLabelView.ts @@ -45,7 +45,7 @@ export default class CrosshairHorizontalLabelView extend const text = this.getText(crosshair, chartStore, axis) ctx.font = createFont(textStyles.size, textStyles.weight, textStyles.family) this.createFigure( - 'rectText', + 'text', this.getTextAttrs(text, ctx.measureText(text).width, crosshair, bounding, axis, textStyles), textStyles )?.draw(ctx) @@ -58,8 +58,8 @@ export default class CrosshairHorizontalLabelView extend return crosshair.paneId === paneId } - protected getDirectionStyles (styels: CrosshairStyle): CrosshairDirectionStyle { - return styels.horizontal + protected getDirectionStyles (styles: CrosshairStyle): CrosshairDirectionStyle { + return styles.horizontal } protected getText (crosshair: Crosshair, chartStore: ChartStore, axis: C): string { diff --git a/src/view/IndicatorLastValueView.ts b/src/view/IndicatorLastValueView.ts index c9c288e17..0983e0347 100644 --- a/src/view/IndicatorLastValueView.ts +++ b/src/view/IndicatorLastValueView.ts @@ -62,7 +62,7 @@ export default class IndicatorLastValueView extends View { } this.createFigure( - 'rectText', + 'text', { x, y, diff --git a/src/view/IndicatorTooltipView.ts b/src/view/IndicatorTooltipView.ts index 1cbcf4a17..7fc62794b 100644 --- a/src/view/IndicatorTooltipView.ts +++ b/src/view/IndicatorTooltipView.ts @@ -16,7 +16,7 @@ import Nullable from '../common/Nullable' import Bounding from '../common/Bounding' import KLineData from '../common/KLineData' import Crosshair from '../common/Crosshair' -import { IndicatorStyle, TooltipStyle, TooltipIconStyle, MarginTextStyle, TooltipData, TooltipShowRule, TooltipDataChild, TooltipIconPosition, CustomApi } from '../common/Options' +import { IndicatorStyle, TooltipStyle, TooltipIconStyle, TooltipTextStyle, TooltipData, TooltipShowRule, TooltipDataChild, TooltipIconPosition, CustomApi } from '../common/Options' import { ActionType } from '../common/Action' import XAxis from '../component/XAxis' @@ -134,9 +134,9 @@ export default class IndicatorTooltipView extends View { prevRowHeight = middleIconsLastRowHeight if (valuesValid) { - const [valuesStartX, valuestartY, valuesLastRowHeight, valuesIncreaseHeight] = this.drawStandardTooltipLabels(ctx, bounding, values, x, y, prevRowHeight, tooltipTextStyles) + const [valuesStartX, valueStartY, valuesLastRowHeight, valuesIncreaseHeight] = this.drawStandardTooltipLabels(ctx, bounding, values, x, y, prevRowHeight, tooltipTextStyles) x = valuesStartX - y = valuestartY + y = valueStartY height += valuesIncreaseHeight prevRowHeight = valuesLastRowHeight } @@ -198,7 +198,7 @@ export default class IndicatorTooltipView extends View { x += marginLeft const active = activeIconInfo?.paneId === currentIconInfo.paneId && activeIconInfo?.indicatorName === currentIconInfo.indicatorName && activeIconInfo?.iconId === icon.id this.createFigure( - 'rectText', + 'text', { text, x, y: y + marginTop }, { paddingLeft, @@ -228,7 +228,7 @@ export default class IndicatorTooltipView extends View { startX: number, startY: number, prevRowHeight: number, - styles: Omit + styles: TooltipTextStyle ): [number, number, number, number] { let x = startX let y = startY diff --git a/src/view/OverlayView.ts b/src/view/OverlayView.ts index b049ef2fa..f7633ed62 100644 --- a/src/view/OverlayView.ts +++ b/src/view/OverlayView.ts @@ -199,7 +199,7 @@ export default class OverlayView extends View { mouseDownEvent: this._figureMouseDownEvent(overlay, figureType, figureKey, figureIndex, attrsIndex), mouseClickEvent: this._figureMouseClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex), mouseRightClickEvent: this._figureMouseRightClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex), - mouseDoubleClickEvent: this._figureMousedbClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex) + mouseDoubleClickEvent: this._figureMouseDoubleClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex) } } eventHandler = {} @@ -218,7 +218,7 @@ export default class OverlayView extends View { eventHandler.mouseClickEvent = this._figureMouseClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex) } if (!eventTypes.includes('mouseDoubleClickEvent') && !eventTypes.includes('doubleTapEvent')) { - eventHandler.mouseDoubleClickEvent = this._figureMousedbClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex) + eventHandler.mouseDoubleClickEvent = this._figureMouseDoubleClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex) } if (!eventTypes.includes('mouseRightClickEvent')) { eventHandler.mouseRightClickEvent = this._figureMouseRightClickEvent(overlay, figureType, figureKey, figureIndex, attrsIndex) @@ -260,7 +260,7 @@ export default class OverlayView extends View { } } - private _figureMousedbClickEvent (overlay: Overlay, _figureType: EventOverlayInfoFigureType, figureKey: string, figureIndex: number, _attrsIndex: number): MouseTouchEventCallback { + private _figureMouseDoubleClickEvent (overlay: Overlay, _figureType: EventOverlayInfoFigureType, figureKey: string, figureIndex: number, _attrsIndex: number): MouseTouchEventCallback { return (event: MouseTouchEvent) => { overlay.onDoubleClick?.({ ...event, figureIndex, figureKey, overlay }) return true @@ -476,10 +476,10 @@ export default class OverlayView extends View { const { type, styles, attrs, ignoreEvent } = figure const attrsArray = [].concat(attrs) attrsArray.forEach((ats, attrsIndex) => { - const evnets = this._createFigureEvents(overlay, EventOverlayInfoFigureType.Other, figure.key ?? '', figureIndex, attrsIndex, ignoreEvent) + const events = this._createFigureEvents(overlay, EventOverlayInfoFigureType.Other, figure.key ?? '', figureIndex, attrsIndex, ignoreEvent) const ss = { ...defaultStyles[type], ...overlay.styles?.[type], ...styles } this.createFigure( - type, ats, ss, evnets + type, ats, ss, events )?.draw(ctx) }) }) diff --git a/src/view/OverlayXAxisView.ts b/src/view/OverlayXAxisView.ts index 5eaf89be8..997bd4410 100644 --- a/src/view/OverlayXAxisView.ts +++ b/src/view/OverlayXAxisView.ts @@ -66,7 +66,7 @@ export default class OverlayXAxisView extends OverlayYAxisView { const point = overlay.points[index] if (point.timestamp !== undefined) { const text = customApi.formatDate(dateTimeFormat, point.timestamp, 'YYYY-MM-DD HH:mm', FormatDateType.Crosshair) - figures.push({ type: 'rectText', attrs: { x: coordinate.x, y: 0, text, align: 'center' }, ignoreEvent: true }) + figures.push({ type: 'text', attrs: { x: coordinate.x, y: 0, text, align: 'center' }, ignoreEvent: true }) } }) if (coordinates.length > 1) { diff --git a/src/view/OverlayYAxisView.ts b/src/view/OverlayYAxisView.ts index 8b9ec0ce5..7e4720faf 100644 --- a/src/view/OverlayYAxisView.ts +++ b/src/view/OverlayYAxisView.ts @@ -94,7 +94,7 @@ export default class OverlayYAxisView extends OverlayVie topY = Math.min(topY, coordinate.y) bottomY = Math.max(bottomY, coordinate.y) const text = formatThousands(formatPrecision(point.value, precision.price), thousandsSeparator) - figures.push({ type: 'rectText', attrs: { x, y: coordinate.y, text, align: textAlign, baseline: 'middle' }, ignoreEvent: true }) + figures.push({ type: 'text', attrs: { x, y: coordinate.y, text, align: textAlign, baseline: 'middle' }, ignoreEvent: true }) } }) if (coordinates.length > 1) {