From b2c0e2a61ad44da72e658f9057f40849fe6b39a8 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 12 Apr 2021 10:59:48 +0200 Subject: [PATCH] feat: LimitLine custom renderer and more options --- src/charting/components/AxisBase.ts | 7 ++ src/charting/components/LimitLine.ts | 5 +- src/charting/components/XAxis.ts | 2 +- src/charting/renderer/AxisRenderer.ts | 3 + src/charting/renderer/XAxisRenderer.ts | 115 ++++++++++++------ .../XAxisRendererHorizontalBarChart.ts | 79 ++++++++---- src/charting/renderer/YAxisRenderer.ts | 96 +++++++++------ .../YAxisRendererHorizontalBarChart.ts | 98 +++++++++------ 8 files changed, 267 insertions(+), 138 deletions(-) diff --git a/src/charting/components/AxisBase.ts b/src/charting/components/AxisBase.ts index 57657339..6693996e 100644 --- a/src/charting/components/AxisBase.ts +++ b/src/charting/components/AxisBase.ts @@ -121,6 +121,13 @@ export abstract class AxisBase extends ComponentBase { * flag indicating the limit lines layer depth */ protected mDrawLimitLineBehindData = false; + + /** + * When enabled, the limitlines will be clipped to contentRect, + * otherwise they can bleed outside the content rect. + */ + public clipLimitLinesToContent = true; + /** * flag indicating the labels layer depth */ diff --git a/src/charting/components/LimitLine.ts b/src/charting/components/LimitLine.ts index b203ade9..a57e52d7 100644 --- a/src/charting/components/LimitLine.ts +++ b/src/charting/components/LimitLine.ts @@ -1,11 +1,14 @@ import { ComponentBase } from './ComponentBase'; import { DashPathEffect, Paint, Style, parseDashEffect } from '@nativescript-community/ui-canvas'; import { Utils } from '../utils/Utils'; +import { Color } from '@nativescript/core'; /** enum that indicates the position of the LimitLine label */ export enum LimitLabelPosition { LEFT_TOP, LEFT_BOTTOM, + CENTER_TOP, + CENTER_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM } @@ -24,7 +27,7 @@ export class LimitLine extends ComponentBase { private mLineWidth = 2; /** the color of the limit line */ - private mLineColor = '#ED5B5B'; + private mLineColor: Color | string = '#ED5B5B'; /** the style of the label text */ private mTextStyle = Style.FILL_AND_STROKE; diff --git a/src/charting/components/XAxis.ts b/src/charting/components/XAxis.ts index 46749229..a54a7692 100644 --- a/src/charting/components/XAxis.ts +++ b/src/charting/components/XAxis.ts @@ -9,7 +9,7 @@ export enum XAxisPosition { BOTTOM, BOTH_SIDED, TOP_INSIDE, - BOTTOM_INSIDE, + BOTTOM_INSIDE } /** diff --git a/src/charting/renderer/AxisRenderer.ts b/src/charting/renderer/AxisRenderer.ts index 617d8578..8c33b96f 100644 --- a/src/charting/renderer/AxisRenderer.ts +++ b/src/charting/renderer/AxisRenderer.ts @@ -5,10 +5,13 @@ import { ViewPortHandler } from '../utils/ViewPortHandler'; import { Transformer } from '../utils/Transformer'; import { Utils } from '../utils/Utils'; import { BaseCustomRenderer } from './DataRenderer'; +import { LimitLine } from '../components/LimitLine'; export type CustomRendererGridLineFunction = (c: Canvas, renderer: AxisRenderer, rect: RectF, x, y, axisValue, paint: Paint) => void; +export type CustomRendererLimitLineFunction = (c: Canvas, renderer: AxisRenderer, limitLine: LimitLine, rect: RectF, x: number, paint: Paint) => void; export interface CustomRenderer extends BaseCustomRenderer { drawGridLine?: CustomRendererGridLineFunction; + drawLimitLine?: CustomRendererLimitLineFunction; } /** diff --git a/src/charting/renderer/XAxisRenderer.ts b/src/charting/renderer/XAxisRenderer.ts index 6e6ebfff..8f01dff5 100644 --- a/src/charting/renderer/XAxisRenderer.ts +++ b/src/charting/renderer/XAxisRenderer.ts @@ -1,4 +1,4 @@ -import { AxisRenderer, CustomRenderer, CustomRendererGridLineFunction } from './AxisRenderer'; +import { AxisRenderer, CustomRenderer, CustomRendererGridLineFunction, CustomRendererLimitLineFunction } from './AxisRenderer'; import { XAxis, XAxisPosition } from '../components/XAxis'; import { ViewPortHandler } from '../utils/ViewPortHandler'; import { Transformer } from '../utils/Transformer'; @@ -316,8 +316,13 @@ export class XAxisRenderer extends AxisRenderer { return this.mRenderLimitLinesBuffer; } - protected mLimitLineClippingRect = new RectF(0, 0, 0, 0); - + protected mLimitLineClippingRect: RectF; + protected get limitLineClippingRect() { + if (!this.mLimitLineClippingRect) { + this.mLimitLineClippingRect = new RectF(0, 0, 0, 0); + } + return this.mLimitLineClippingRect; + } /** * Draws the LimitLines associated with this axis to the screen. * @@ -325,7 +330,8 @@ export class XAxisRenderer extends AxisRenderer { */ public renderLimitLines(c: Canvas) { - const limitLines = this.mXAxis.getLimitLines(); + const axis = this.mXAxis; + const limitLines = axis.getLimitLines(); if (limitLines == null || limitLines.length <= 0) return; @@ -333,17 +339,22 @@ export class XAxisRenderer extends AxisRenderer { position[0] = 0; position[1] = 0; - const rect = this.mAxis.isIgnoringOffsets() ? this.mViewPortHandler.getChartRect() : this.mViewPortHandler.getContentRect(); + const rect = axis.isIgnoringOffsets() ? this.mViewPortHandler.getChartRect() : this.mViewPortHandler.getContentRect(); + const clipToContent = axis.clipLimitLinesToContent; + const customRender = axis.getCustomRenderer(); + const customRenderFunction = customRender && customRender.drawLimitLine; for (let i = 0; i < limitLines.length; i++) { const l = limitLines[i]; if (!l.isEnabled()) continue; const lineWidth = l.getLineWidth(); - - const clipRestoreCount = c.save(); - this.mLimitLineClippingRect.set(rect); - this.mLimitLineClippingRect.inset(-lineWidth, 0); - c.clipRect(this.mLimitLineClippingRect); + if (clipToContent) { + c.save(); + const clipRect = this.limitLineClippingRect; + clipRect.set(rect); + clipRect.inset(0, -lineWidth); + c.clipRect(clipRect); + } position[0] = l.getLimit(); position[1] = 0; @@ -351,35 +362,39 @@ export class XAxisRenderer extends AxisRenderer { this.mTrans.pointValuesToPixel(position); if (lineWidth > 0) { - this.renderLimitLineLine(c, l, position); + this.renderLimitLineLine(c, l, rect, position[0], customRenderFunction); } this.renderLimitLineLabel(c, l, position, 2 + l.getYOffset()); - c.restoreToCount(clipRestoreCount); + if (clipToContent) { + c.restore(); + } } } - private mLimitLineSegmentsBuffer = []; - private mLimitLinePath = new Path(); + // private mLimitLineSegmentsBuffer = []; + // private mLimitLinePath = new Path(); - public renderLimitLineLine(c: Canvas, limitLine: LimitLine, position) { - const rect = this.mAxis.isIgnoringOffsets() ? this.mViewPortHandler.getChartRect() : this.mViewPortHandler.getContentRect(); - this.mLimitLineSegmentsBuffer[0] = position[0]; - this.mLimitLineSegmentsBuffer[1] = rect.top; - this.mLimitLineSegmentsBuffer[2] = position[0]; - this.mLimitLineSegmentsBuffer[3] = rect.bottom; + public renderLimitLineLine(c: Canvas, limitLine: LimitLine, rect: RectF, x: number, customRendererFunc?: CustomRendererLimitLineFunction) { + // this.mLimitLineSegmentsBuffer[0] = position[0]; + // this.mLimitLineSegmentsBuffer[1] = rect.top; + // this.mLimitLineSegmentsBuffer[2] = position[0]; + // this.mLimitLineSegmentsBuffer[3] = rect.bottom; - this.mLimitLinePath.reset(); - this.mLimitLinePath.moveTo(this.mLimitLineSegmentsBuffer[0], this.mLimitLineSegmentsBuffer[1]); - this.mLimitLinePath.lineTo(this.mLimitLineSegmentsBuffer[2], this.mLimitLineSegmentsBuffer[3]); + // this.mLimitLinePath.reset(); + // this.mLimitLinePath.moveTo(this.mLimitLineSegmentsBuffer[0], this.mLimitLineSegmentsBuffer[1]); + // this.mLimitLinePath.lineTo(this.mLimitLineSegmentsBuffer[2], this.mLimitLineSegmentsBuffer[3]); const paint = this.limitLinePaint; - paint.setStyle(Style.STROKE); + // paint.setStyle(Style.STROKE); paint.setColor(limitLine.getLineColor()); paint.setStrokeWidth(limitLine.getLineWidth()); paint.setPathEffect(limitLine.getDashPathEffect()); - - c.drawPath(this.mLimitLinePath, paint); + if (customRendererFunc) { + customRendererFunc(c, this, limitLine, rect, x, paint); + } else { + c.drawLine(x, rect.bottom, x, rect.top, paint); + } } public renderLimitLineLabel(c: Canvas, limitLine: LimitLine, position, yOffset) { @@ -399,20 +414,40 @@ export class XAxisRenderer extends AxisRenderer { const labelPosition = limitLine.getLabelPosition(); - if (labelPosition === LimitLabelPosition.RIGHT_TOP) { - const labelLineHeight = Utils.calcTextHeight(paint, label); - paint.setTextAlign(Align.LEFT); - c.drawText(label, position[0] + xOffset, rect.top + yOffset + labelLineHeight, paint); - } else if (labelPosition === LimitLabelPosition.RIGHT_BOTTOM) { - paint.setTextAlign(Align.LEFT); - c.drawText(label, position[0] + xOffset, rect.bottom - yOffset, paint); - } else if (labelPosition === LimitLabelPosition.LEFT_TOP) { - paint.setTextAlign(Align.RIGHT); - const labelLineHeight = Utils.calcTextHeight(paint, label); - c.drawText(label, position[0] - xOffset, rect.top + yOffset + labelLineHeight, paint); - } else { - paint.setTextAlign(Align.RIGHT); - c.drawText(label, position[0] - xOffset, rect.bottom - yOffset, paint); + switch (labelPosition) { + case LimitLabelPosition.CENTER_TOP: { + const labelLineHeight = Utils.calcTextHeight(paint, label); + paint.setTextAlign(Align.CENTER); + c.drawText(label, position[0], rect.top + yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.CENTER_BOTTOM: { + paint.setTextAlign(Align.CENTER); + c.drawText(label, position[0], rect.bottom - yOffset, paint); + break; + } + case LimitLabelPosition.RIGHT_TOP: { + const labelLineHeight = Utils.calcTextHeight(paint, label); + paint.setTextAlign(Align.LEFT); + c.drawText(label, position[0] + xOffset, rect.top + yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.RIGHT_BOTTOM: { + paint.setTextAlign(Align.LEFT); + c.drawText(label, position[0] + xOffset, rect.bottom - yOffset, paint); + break; + } + case LimitLabelPosition.LEFT_TOP: { + paint.setTextAlign(Align.RIGHT); + const labelLineHeight = Utils.calcTextHeight(paint, label); + c.drawText(label, position[0] - xOffset, rect.top + yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.LEFT_BOTTOM: { + paint.setTextAlign(Align.RIGHT); + c.drawText(label, position[0] - xOffset, rect.bottom - yOffset, paint); + break; + } } } } diff --git a/src/charting/renderer/XAxisRendererHorizontalBarChart.ts b/src/charting/renderer/XAxisRendererHorizontalBarChart.ts index 49a95b81..369d462b 100644 --- a/src/charting/renderer/XAxisRendererHorizontalBarChart.ts +++ b/src/charting/renderer/XAxisRendererHorizontalBarChart.ts @@ -188,7 +188,8 @@ export class XAxisRendererHorizontalBarChart extends XAxisRenderer { */ public renderLimitLines(c: Canvas) { - const limitLines = this.mXAxis.getLimitLines(); + const axis = this.mXAxis; + const limitLines = axis.getLimitLines(); if (limitLines == null || limitLines.length <= 0) return; @@ -200,35 +201,46 @@ export class XAxisRendererHorizontalBarChart extends XAxisRenderer { limitLinePath.reset(); let offsetLeft = 0; let rect: RectF; - if (this.mAxis.isIgnoringOffsets()) { + if (axis.isIgnoringOffsets()) { rect = this.mViewPortHandler.getChartRect(); } else { rect = this.mViewPortHandler.getContentRect(); offsetLeft = this.mViewPortHandler.offsetLeft(); } + const customRender = axis.getCustomRenderer(); + const customRendererFunc = customRender && customRender.drawLimitLine; + const clipToContent = axis.clipLimitLinesToContent; for (let i = 0; i < limitLines.length; i++) { const l = limitLines[i]; if (!l.isEnabled()) { continue; } - - const clipRestoreCount = c.save(); - this.mLimitLineClippingRect.set(rect); - this.mLimitLineClippingRect.inset(0, -l.getLineWidth()); - c.clipRect(this.mLimitLineClippingRect); + const lineWidth = l.getLineWidth(); + if (clipToContent) { + const clipRect = this.limitLineClippingRect; + clipRect.set(rect); + clipRect.inset(0, -lineWidth); + c.clipRect(clipRect); + } const paint = this.limitLinePaint; - paint.setStyle(Style.STROKE); paint.setColor(l.getLineColor()); - paint.setStrokeWidth(l.getLineWidth()); + paint.setStrokeWidth(lineWidth); paint.setPathEffect(l.getDashPathEffect()); pts[1] = l.getLimit(); this.mTrans.pointValuesToPixel(pts); - limitLinePath.moveTo(rect.left, pts[1]); + if (lineWidth > 0) { + if (customRendererFunc) { + customRendererFunc(c, this, l, rect, pts[1], paint); + } else { + c.drawLine(rect.left, pts[1], rect.right, pts[1], paint); + } + } + limitLinePath.lineTo(rect.right, pts[1]); c.drawPath(limitLinePath, paint); @@ -250,22 +262,43 @@ export class XAxisRendererHorizontalBarChart extends XAxisRenderer { const position = l.getLabelPosition(); - if (position === LimitLabelPosition.RIGHT_TOP) { - paint.setTextAlign(Align.RIGHT); - c.drawText(label, rect.right - xOffset, pts[1] - yOffset + labelLineHeight, paint); - } else if (position === LimitLabelPosition.RIGHT_BOTTOM) { - paint.setTextAlign(Align.RIGHT); - c.drawText(label, rect.right - xOffset, pts[1] + yOffset, paint); - } else if (position === LimitLabelPosition.LEFT_TOP) { - paint.setTextAlign(Align.LEFT); - c.drawText(label, rect.left + xOffset, pts[1] - yOffset + labelLineHeight, paint); - } else { - paint.setTextAlign(Align.LEFT); - c.drawText(label, offsetLeft + xOffset, pts[1] + yOffset, paint); + switch (position) { + case LimitLabelPosition.RIGHT_TOP: { + paint.setTextAlign(Align.RIGHT); + c.drawText(label, rect.right - xOffset, pts[1] - yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.RIGHT_BOTTOM: { + paint.setTextAlign(Align.RIGHT); + c.drawText(label, rect.right - xOffset, pts[1] + yOffset, paint); + break; + } + case LimitLabelPosition.CENTER_TOP: { + paint.setTextAlign(Align.CENTER); + c.drawText(label, rect.right, pts[1] - yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.CENTER_BOTTOM: { + paint.setTextAlign(Align.CENTER); + c.drawText(label, rect.right, pts[1] + yOffset, paint); + break; + } + case LimitLabelPosition.LEFT_TOP: { + paint.setTextAlign(Align.LEFT); + c.drawText(label, rect.left + xOffset, pts[1] - yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.LEFT_BOTTOM: { + paint.setTextAlign(Align.LEFT); + c.drawText(label, offsetLeft + xOffset, pts[1] + yOffset, paint); + break; + } } } - c.restoreToCount(clipRestoreCount); + if (clipToContent) { + c.restore(); + } } } } diff --git a/src/charting/renderer/YAxisRenderer.ts b/src/charting/renderer/YAxisRenderer.ts index ab3ce7dd..a3a68029 100644 --- a/src/charting/renderer/YAxisRenderer.ts +++ b/src/charting/renderer/YAxisRenderer.ts @@ -36,13 +36,13 @@ export class YAxisRenderer extends AxisRenderer { return this.mZeroLineClippingRect; } - protected mRenderLimitLinesPath: Path; - protected get renderLimitLinesPath() { - if (!this.mRenderLimitLinesPath) { - this.mRenderLimitLinesPath = new Path(); - } - return this.mRenderLimitLinesPath; - } + // protected mRenderLimitLinesPath: Path; + // protected get renderLimitLinesPath() { + // if (!this.mRenderLimitLinesPath) { + // this.mRenderLimitLinesPath = new Path(); + // } + // return this.mRenderLimitLinesPath; + // } protected mRenderLimitLinesBuffer; protected get renderLimitLinesBuffer() { if (!this.mRenderLimitLinesBuffer) { @@ -315,36 +315,40 @@ export class YAxisRenderer extends AxisRenderer { * @param c */ public renderLimitLines(c: Canvas) { - const limitLines = this.mYAxis.getLimitLines(); + const axis = this.mYAxis; + const limitLines = axis.getLimitLines(); if (limitLines == null || limitLines.length <= 0) return; const pts = this.renderLimitLinesBuffer; pts[0] = 0; pts[1] = 0; - const limitLinePath = this.renderLimitLinesPath; - limitLinePath.reset(); let offsetLeft = 0; let rect: RectF; - if (this.mAxis.isIgnoringOffsets()) { + if (axis.isIgnoringOffsets()) { rect = this.mViewPortHandler.getChartRect(); } else { rect = this.mViewPortHandler.getContentRect(); offsetLeft = this.mViewPortHandler.offsetLeft(); } + + const customRender = axis.getCustomRenderer(); + const customRendererFunc = customRender && customRender.drawLimitLine; + const clipToContent = axis.clipLimitLinesToContent; for (let i = 0; i < limitLines.length; i++) { const l = limitLines[i]; if (!l.isEnabled()) continue; const lineWidth = l.getLineWidth(); - const clipRestoreCount = c.save(); - const rect = this.limitLineClippingRect; - rect.set(rect); - rect.inset(0, -lineWidth); - c.clipRect(rect); + if (clipToContent) { + c.save(); + const clipRect = this.limitLineClippingRect; + clipRect.set(rect); + clipRect.inset(0, -lineWidth); + c.clipRect(clipRect); + } const paint = this.limitLinePaint; - paint.setStyle(Style.STROKE); paint.setColor(l.getLineColor()); paint.setStrokeWidth(lineWidth); paint.setPathEffect(l.getDashPathEffect()); @@ -353,12 +357,12 @@ export class YAxisRenderer extends AxisRenderer { this.mTrans.pointValuesToPixel(pts); if (lineWidth > 0) { - limitLinePath.moveTo(rect.left, pts[1]); - limitLinePath.lineTo(rect.right, pts[1]); - c.drawPath(limitLinePath, paint); - limitLinePath.reset(); + if (customRendererFunc) { + customRendererFunc(c, this, l, rect, pts[1], paint); + } else { + c.drawLine(rect.left, pts[1], rect.right, pts[1], paint); + } } - // c.drawLines(pts, paint); const label = l.getLabel(); @@ -375,23 +379,43 @@ export class YAxisRenderer extends AxisRenderer { const yOffset = l.getLineWidth() + labelLineHeight + l.getYOffset(); const position = l.getLabelPosition(); - - if (position === LimitLabelPosition.RIGHT_TOP) { - paint.setTextAlign(Align.RIGHT); - c.drawText(label, rect.right - xOffset, pts[1] - yOffset + labelLineHeight, paint); - } else if (position === LimitLabelPosition.RIGHT_BOTTOM) { - paint.setTextAlign(Align.RIGHT); - c.drawText(label, rect.right - xOffset, pts[1] + yOffset, paint); - } else if (position === LimitLabelPosition.LEFT_TOP) { - paint.setTextAlign(Align.LEFT); - c.drawText(label, rect.left + xOffset, pts[1] - yOffset + labelLineHeight, paint); - } else { - paint.setTextAlign(Align.LEFT); - c.drawText(label, offsetLeft + xOffset, pts[1] + yOffset, paint); + switch (position) { + case LimitLabelPosition.RIGHT_TOP: { + paint.setTextAlign(Align.RIGHT); + c.drawText(label, rect.right - xOffset, pts[1] - yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.RIGHT_BOTTOM: { + paint.setTextAlign(Align.RIGHT); + c.drawText(label, rect.right - xOffset, pts[1] + yOffset, paint); + break; + } + case LimitLabelPosition.CENTER_TOP: { + paint.setTextAlign(Align.RIGHT); + c.drawText(label, rect.right, pts[1] - yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.CENTER_BOTTOM: { + paint.setTextAlign(Align.CENTER); + c.drawText(label, rect.right, pts[1] + yOffset, paint); + break; + } + case LimitLabelPosition.LEFT_TOP: { + paint.setTextAlign(Align.LEFT); + c.drawText(label, rect.left + xOffset, pts[1] - yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.LEFT_BOTTOM: { + paint.setTextAlign(Align.LEFT); + c.drawText(label, offsetLeft + xOffset, pts[1] + yOffset, paint); + break; + } } } - c.restoreToCount(clipRestoreCount); + if (clipToContent) { + c.restore(); + } } } } diff --git a/src/charting/renderer/YAxisRendererHorizontalBarChart.ts b/src/charting/renderer/YAxisRendererHorizontalBarChart.ts index ef68472a..00e8f781 100644 --- a/src/charting/renderer/YAxisRendererHorizontalBarChart.ts +++ b/src/charting/renderer/YAxisRendererHorizontalBarChart.ts @@ -17,7 +17,7 @@ export class YAxisRendererHorizontalBarChart extends YAxisRenderer { } protected get renderLimitLinesBuffer() { if (!this.mRenderLimitLinesBuffer) { - this.mRenderLimitLinesBuffer = Utils.createNativeArray(4); + this.mRenderLimitLinesBuffer = Utils.createNativeArray(2); } return this.mRenderLimitLinesBuffer; } @@ -198,7 +198,8 @@ export class YAxisRendererHorizontalBarChart extends YAxisRenderer { */ public renderLimitLines(c: Canvas) { - const limitLines = this.mYAxis.getLimitLines(); + const axis = this.mYAxis; + const limitLines = axis.getLimitLines(); if (limitLines == null || limitLines.length <= 0) { return; @@ -207,12 +208,13 @@ export class YAxisRendererHorizontalBarChart extends YAxisRenderer { const pts = this.renderLimitLinesBuffer; pts[0] = 0; pts[1] = 0; - pts[2] = 0; - pts[3] = 0; - const limitLinePath = this.renderLimitLinesPath; - limitLinePath.reset(); + // const limitLinePath = this.renderLimitLinesPath; + // limitLinePath.reset(); - const rect = this.mAxis.isIgnoringOffsets() ? this.mViewPortHandler.getChartRect() : this.mViewPortHandler.getContentRect(); + const customRender = axis.getCustomRenderer(); + const customRendererFunc = customRender && customRender.drawLimitLine; + const rect = axis.isIgnoringOffsets() ? this.mViewPortHandler.getChartRect() : this.mViewPortHandler.getContentRect(); + const clipToContent = axis.clipLimitLinesToContent; for (let i = 0; i < limitLines.length; i++) { const l = limitLines[i]; @@ -220,31 +222,31 @@ export class YAxisRendererHorizontalBarChart extends YAxisRenderer { continue; } - const clipRestoreCount = c.save(); - this.mLimitLineClippingRect.set(rect); - this.mLimitLineClippingRect.inset(-l.getLineWidth(), 0); - c.clipRect(this.mLimitLineClippingRect); + const lineWidth = l.getLineWidth(); + if (clipToContent) { + c.save(); + const clipRect = this.limitLineClippingRect; + clipRect.set(rect); + clipRect.inset(0, -lineWidth); + c.clipRect(clipRect); + } pts[0] = l.getLimit(); - pts[2] = l.getLimit(); this.mTrans.pointValuesToPixel(pts); - pts[1] = rect.top; - pts[3] = rect.bottom; - - limitLinePath.moveTo(pts[0], pts[1]); - limitLinePath.lineTo(pts[2], pts[3]); - const paint = this.limitLinePaint; - // paint.setTextAlign(Align.LEFT); - paint.setStyle(Style.STROKE); paint.setColor(l.getLineColor()); paint.setPathEffect(l.getDashPathEffect()); paint.setStrokeWidth(l.getLineWidth()); - c.drawPath(limitLinePath, paint); - limitLinePath.reset(); + if (lineWidth > 0) { + if (customRendererFunc) { + customRendererFunc(c, this, l, rect, pts[0], paint); + } else { + c.drawLine(pts[0], rect.bottom, pts[0], rect.top, paint); + } + } const label = l.getLabel(); @@ -262,24 +264,46 @@ export class YAxisRendererHorizontalBarChart extends YAxisRenderer { const position = l.getLabelPosition(); - if (position === LimitLabelPosition.RIGHT_TOP) { - const labelLineHeight = Utils.calcTextHeight(paint, label); - paint.setTextAlign(Align.LEFT); - c.drawText(label, pts[0] + xOffset, rect.top + yOffset + labelLineHeight, paint); - } else if (position === LimitLabelPosition.RIGHT_BOTTOM) { - paint.setTextAlign(Align.LEFT); - c.drawText(label, pts[0] + xOffset, rect.bottom - yOffset, paint); - } else if (position === LimitLabelPosition.LEFT_TOP) { - paint.setTextAlign(Align.RIGHT); - const labelLineHeight = Utils.calcTextHeight(paint, label); - c.drawText(label, pts[0] - xOffset, rect.top + yOffset + labelLineHeight, paint); - } else { - paint.setTextAlign(Align.RIGHT); - c.drawText(label, pts[0] - xOffset, rect.bottom - yOffset, paint); + switch (position) { + case LimitLabelPosition.RIGHT_TOP: { + const labelLineHeight = Utils.calcTextHeight(paint, label); + paint.setTextAlign(Align.LEFT); + c.drawText(label, pts[0] + xOffset, rect.top + yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.RIGHT_BOTTOM: { + paint.setTextAlign(Align.LEFT); + c.drawText(label, pts[0] + xOffset, rect.bottom - yOffset, paint); + break; + } + case LimitLabelPosition.CENTER_TOP: { + const labelLineHeight = Utils.calcTextHeight(paint, label); + paint.setTextAlign(Align.CENTER); + c.drawText(label, pts[0], rect.top + yOffset + labelLineHeight, paint); + break; + } + case LimitLabelPosition.CENTER_BOTTOM: { + paint.setTextAlign(Align.CENTER); + c.drawText(label, pts[0], rect.bottom - yOffset, paint); + break; + } + case LimitLabelPosition.LEFT_TOP: { + paint.setTextAlign(Align.RIGHT); + const labelLineHeight = Utils.calcTextHeight(paint, label); + c.drawText(label, pts[0] - xOffset, rect.top + yOffset + labelLineHeight, paint); + break; + } + default: { + paint.setTextAlign(Align.RIGHT); + c.drawText(label, pts[0] - xOffset, rect.bottom - yOffset, paint); + break; + } } } - c.restoreToCount(clipRestoreCount); + if (clipToContent) { + c.restore(); + } } } }