From 916217675769973a446a98048dd5f91c902ee176 Mon Sep 17 00:00:00 2001 From: Matteo Koczorek Date: Wed, 2 Aug 2017 15:44:02 +0200 Subject: [PATCH 1/2] added support for axis ticks --- .../Charts/Charts/BarLineChartViewBase.swift | 2 + Source/Charts/Components/AxisBase.swift | 7 +++ .../Charts/Renderers/AxisRendererBase.swift | 6 +++ Source/Charts/Renderers/XAxisRenderer.swift | 54 +++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/Source/Charts/Charts/BarLineChartViewBase.swift b/Source/Charts/Charts/BarLineChartViewBase.swift index 747120718f..2aae56d82a 100644 --- a/Source/Charts/Charts/BarLineChartViewBase.swift +++ b/Source/Charts/Charts/BarLineChartViewBase.swift @@ -252,6 +252,8 @@ open class BarLineChartViewBase: ChartViewBase, BarLineScatterCandleBubbleChartD _xAxisRenderer.renderAxisLabels(context: context) _leftYAxisRenderer.renderAxisLabels(context: context) _rightYAxisRenderer.renderAxisLabels(context: context) + _xAxisRenderer.renderTickLines(context: context) + _rightYAxisRenderer.renderTickLines(context: context) if clipValuesToContentEnabled { diff --git a/Source/Charts/Components/AxisBase.swift b/Source/Charts/Components/AxisBase.swift index 160872e097..0add32ace9 100644 --- a/Source/Charts/Components/AxisBase.swift +++ b/Source/Charts/Components/AxisBase.swift @@ -31,15 +31,20 @@ open class AxisBase: ComponentBase open var axisLineWidth = CGFloat(0.5) open var axisLineDashPhase = CGFloat(0.0) open var axisLineDashLengths: [CGFloat]! + open var tickLineColor = NSUIColor.white open var gridColor = NSUIColor.gray.withAlphaComponent(0.9) open var gridLineWidth = CGFloat(0.5) open var gridLineDashPhase = CGFloat(0.0) open var gridLineDashLengths: [CGFloat]! open var gridLineCap = CGLineCap.butt + open var tickLineLength = CGFloat(10) + open var tickLineWidth = CGFloat(1) + open var tickLineOffset = CGFloat(-5) open var drawGridLinesEnabled = true open var drawAxisLineEnabled = true + open var drawTickLinesEnabled = true /// flag that indicates of the labels of this axis should be drawn or not open var drawLabelsEnabled = true @@ -183,6 +188,8 @@ open class AxisBase: ComponentBase open var isDrawLabelsEnabled: Bool { return drawLabelsEnabled } + open var isDrawTickLinesEnabled: Bool { return drawTickLinesEnabled } + /// Are the LimitLines drawn behind the data or in front of the data? /// /// **default**: false diff --git a/Source/Charts/Renderers/AxisRendererBase.swift b/Source/Charts/Renderers/AxisRendererBase.swift index 0032c13dc2..6c3934ff00 100644 --- a/Source/Charts/Renderers/AxisRendererBase.swift +++ b/Source/Charts/Renderers/AxisRendererBase.swift @@ -58,6 +58,12 @@ open class AxisRendererBase: Renderer fatalError("renderLimitLines() cannot be called on AxisRendererBase") } + /// Draws the TickLines associated with this axis to the screen. + open func renderTickLines(context: CGContext) + { + fatalError("renderTickLines() cannot be called on AxisRendererBase") + } + /// Computes the axis values. /// - parameter min: the minimum value in the data object for this axis /// - parameter max: the maximum value in the data object for this axis diff --git a/Source/Charts/Renderers/XAxisRenderer.swift b/Source/Charts/Renderers/XAxisRenderer.swift index 7bec034e63..0beaa172c3 100644 --- a/Source/Charts/Renderers/XAxisRenderer.swift +++ b/Source/Charts/Renderers/XAxisRenderer.swift @@ -353,6 +353,60 @@ open class XAxisRenderer: AxisRendererBase } } + // MARK: - Ticks + open override func renderTickLines(context: CGContext) + { + guard + let xAxis = self.axis as? XAxis, + let transformer = self.transformer + else { return } + + if !xAxis.isDrawTickLinesEnabled + { + return + } + + context.saveGState() + defer { context.restoreGState() } + + context.setShouldAntialias(xAxis.gridAntialiasEnabled) + context.setStrokeColor(xAxis.tickLineColor.cgColor) + context.setLineWidth(xAxis.tickLineWidth) + context.setLineCap(xAxis.gridLineCap) + context.setLineDash(phase: 0.0, lengths: []) + + let valueToPixelMatrix = transformer.valueToPixelMatrix + + var position = CGPoint(x: 0.0, y: 0.0) + + let entries = xAxis.entries + + for i in stride(from: 0, to: entries.count, by: 1) + { + position.x = CGFloat(entries[i]) + position.y = position.x + position = position.applying(valueToPixelMatrix) + + drawTickLine(context: context, x: position.x, y: position.y, height: xAxis.tickLineLength) + } + } + + open func drawTickLine(context: CGContext, x: CGFloat, y: CGFloat, height: CGFloat) + { + guard + let viewPortHandler = self.viewPortHandler + else { return } + + if x >= viewPortHandler.offsetLeft + && x <= viewPortHandler.chartWidth + { + context.beginPath() + context.move(to: CGPoint(x: x, y: viewPortHandler.contentBottom-height/2)) + context.addLine(to: CGPoint(x: x, y: viewPortHandler.contentBottom+height/2)) + context.strokePath() + } + } + open override func renderLimitLines(context: CGContext) { guard From a339988e3eec1b4998201e975c1e996fc17b5a32 Mon Sep 17 00:00:00 2001 From: Matteo Koczorek Date: Wed, 2 Aug 2017 15:56:09 +0200 Subject: [PATCH 2/2] implemented y axis rendering ticks --- Source/Charts/Renderers/YAxisRenderer.swift | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Source/Charts/Renderers/YAxisRenderer.swift b/Source/Charts/Renderers/YAxisRenderer.swift index fd9604e868..94cfea0993 100644 --- a/Source/Charts/Renderers/YAxisRenderer.swift +++ b/Source/Charts/Renderers/YAxisRenderer.swift @@ -287,6 +287,47 @@ open class YAxisRenderer: AxisRendererBase context.drawPath(using: CGPathDrawingMode.stroke) } + // MARK: - Ticks + open override func renderTickLines(context: CGContext) + { + guard let + yAxis = self.axis as? YAxis + else { return } + + if !yAxis.isDrawTickLinesEnabled + { + return + } + + let positions = transformedPositions() + + context.saveGState() + defer { context.restoreGState() } + + context.setShouldAntialias(yAxis.gridAntialiasEnabled) + context.setStrokeColor(yAxis.tickLineColor.cgColor) + context.setLineWidth(yAxis.tickLineWidth) + context.setLineCap(yAxis.gridLineCap) + + // draw the grid + for i in 0 ..< positions.count + { + drawTickLine(context: context, position: positions[i], length: yAxis.tickLineLength, offset: yAxis.tickLineOffset) + } + } + + open func drawTickLine(context: CGContext, position: CGPoint, length: CGFloat, offset: CGFloat) + { + guard + let viewPortHandler = self.viewPortHandler + else { return } + + context.beginPath() + context.move(to: CGPoint(x: viewPortHandler.contentRight + offset , y: position.y)) + context.addLine(to: CGPoint(x: viewPortHandler.contentRight + length + offset, y: position.y)) + context.strokePath() + } + open override func renderLimitLines(context: CGContext) { guard