Skip to content

Commit

Permalink
Merge pull request philackm#13 from RedBlueThing/bar-layer
Browse files Browse the repository at this point in the history
Bar layer
  • Loading branch information
philackm committed Jun 4, 2016
2 parents 4c6346f + 4d7556d commit 23b27f2
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 5 deletions.
114 changes: 109 additions & 5 deletions Classes/ScrollableGraphView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import UIKit
// Use these to customise the graph.
// #################################

// Bar styles
public var shouldDrawBarLayer = false
public var barLineWidth: CGFloat = 1
public var barLineColor = UIColor.darkGrayColor()
public var barColor = UIColor.grayColor()
public var barWidth: CGFloat = 25;

// Line Styles
public var lineWidth: CGFloat = 2
public var lineColor = UIColor.blackColor()
Expand Down Expand Up @@ -104,6 +111,7 @@ import UIKit

// Graph Line
private var currentLinePath = UIBezierPath()
private var zeroYPosition: CGFloat = 0

// Labels
private var labelsView = UIView()
Expand All @@ -113,6 +121,7 @@ import UIKit
private var graphPoints = [GraphPoint]()

private var drawingView = UIView()
private var barLayer: BarDrawingLayer?
private var lineLayer: LineDrawingLayer?
private var dataPointLayer: DataPointDrawingLayer?
private var fillLayer: FillDrawingLayer?
Expand Down Expand Up @@ -282,7 +291,7 @@ import UIKit

// Data Point layer
if(shouldDrawDataPoint) {
dataPointLayer = DataPointDrawingLayer(frame: viewport, fillColor: dataPointFillColor, dataPointType: dataPointType, dataPointSize: dataPointSize)
dataPointLayer = DataPointDrawingLayer(frame: viewport, fillColor: dataPointFillColor, dataPointType: dataPointType, dataPointSize: dataPointSize, customDataPointPath: customDataPointPath)
dataPointLayer?.graphViewDrawingDelegate = self
drawingView.layer.insertSublayer(dataPointLayer!, above: lineLayer)
}
Expand All @@ -305,6 +314,18 @@ import UIKit
drawingView.layer.insertSublayer(gradientLayer!, below: lineLayer)
}
}

// The bar layer
if (shouldDrawBarLayer) {
// Bar Layer
barLayer = BarDrawingLayer(frame: viewport,
barWidth: barWidth,
barColor: barColor,
barLineWidth: barLineWidth,
barLineColor: barLineColor)
barLayer?.graphViewDrawingDelegate = self
drawingView.layer.insertSublayer (barLayer!, below: lineLayer)
}
}

private func addReferenceLines(inViewport viewport: CGRect) {
Expand Down Expand Up @@ -659,13 +680,13 @@ import UIKit

let pathSegmentAdder = lineStyle == .Straight ? addStraightLineSegment : addCurvedLineSegment

zeroYPosition = calculatePosition(0, value: self.range.min).y

// Connect the line to the starting edge if we are filling it.
if(shouldFill) {
// Add a line from the base of the graph to the first data point.
let firstDataPoint = graphPoints[activePointsInterval.startIndex]

let zeroYPosition = calculatePosition(0, value: self.range.min).y

let viewportLeftZero = CGPoint(x: firstDataPoint.x - (leftmostPointPadding), y: zeroYPosition)
let leftFarEdgeTop = CGPoint(x: firstDataPoint.x - (leftmostPointPadding + viewportWidth), y: zeroYPosition)
let leftFarEdgeBottom = CGPoint(x: firstDataPoint.x - (leftmostPointPadding + viewportWidth), y: viewportHeight)
Expand Down Expand Up @@ -694,8 +715,6 @@ import UIKit
// Add a line from the last data point to the base of the graph.
let lastDataPoint = graphPoints[activePointsInterval.endIndex]

let zeroYPosition = calculatePosition(0, value: self.range.min).y

let viewportRightZero = CGPoint(x: lastDataPoint.x + (rightmostPointPadding), y: zeroYPosition)
let rightFarEdgeTop = CGPoint(x: lastDataPoint.x + (rightmostPointPadding + viewportWidth), y: zeroYPosition)
let rightFarEdgeBottom = CGPoint(x: lastDataPoint.x + (rightmostPointPadding + viewportWidth), y: viewportHeight)
Expand Down Expand Up @@ -773,11 +792,16 @@ import UIKit

// Update any paths with the new path based on visible data points.
private func updatePaths() {

createLinePath()

if let drawingLayers = drawingView.layer.sublayers {
for layer in drawingLayers {
if let layer = layer as? ScrollableGraphViewDrawingLayer {
// The bar layer needs the zero Y position to set the bottom of the bar
layer.zeroYPosition = zeroYPosition
// Need to make sure this is set in createLinePath
assert (layer.zeroYPosition > 0);
layer.updatePath()
}
}
Expand Down Expand Up @@ -1084,6 +1108,7 @@ private class ScrollableGraphViewDrawingLayer : CAShapeLayer {

var viewportWidth: CGFloat = 0
var viewportHeight: CGFloat = 0
var zeroYPosition: CGFloat = 0

var graphViewDrawingDelegate: ScrollableGraphViewDrawingDelegate? = nil

Expand Down Expand Up @@ -1119,6 +1144,85 @@ private class ScrollableGraphViewDrawingLayer : CAShapeLayer {
}
}

// MARK: Drawing the bars
private class BarDrawingLayer: ScrollableGraphViewDrawingLayer {

private var barPath = UIBezierPath()
private var barWidth: CGFloat = 4

init(frame: CGRect, barWidth: CGFloat, barColor: UIColor, barLineWidth: CGFloat, barLineColor: UIColor) {
super.init(viewportWidth: frame.size.width, viewportHeight: frame.size.height)

self.barWidth = barWidth
self.lineWidth = barLineWidth
self.strokeColor = barLineColor.CGColor
self.fillColor = barColor.CGColor

self.lineJoin = lineJoin
self.lineCap = lineCap
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func createBarPath(centre: CGPoint) -> UIBezierPath {

let squarePath = UIBezierPath()

squarePath.moveToPoint(centre)
let barWidthOffset: CGFloat = self.barWidth / 2

let topLeft = CGPoint(x: centre.x - barWidthOffset, y: centre.y)
let topRight = CGPoint(x: centre.x + barWidthOffset, y: centre.y)
let bottomLeft = CGPoint(x: centre.x - barWidthOffset, y: zeroYPosition)
let bottomRight = CGPoint(x: centre.x + barWidthOffset, y: zeroYPosition)

squarePath.moveToPoint(topLeft)
squarePath.addLineToPoint(topRight)
squarePath.addLineToPoint(bottomRight)
squarePath.addLineToPoint(bottomLeft)
squarePath.addLineToPoint(topLeft)

return squarePath
}

private func createPath () -> UIBezierPath {

barPath.removeAllPoints()

// We can only move forward if we can get the data we need from the delegate.
guard let
activePointsInterval = self.graphViewDrawingDelegate?.intervalForActivePoints(),
data = self.graphViewDrawingDelegate?.dataForGraph()
else {
return barPath
}

let numberOfPoints = min(data.count, activePointsInterval.endIndex)

for i in activePointsInterval.startIndex ... numberOfPoints {

var location = CGPointZero

if let pointLocation = self.graphViewDrawingDelegate?.graphPointForIndex(i).location {
location = pointLocation
}

let pointPath = createBarPath(location)
barPath.appendPath(pointPath)
}

return barPath
}

override func updatePath() {

self.path = createPath ().CGPath
}

}

// MARK: Drawing the Graph Line
private class LineDrawingLayer : ScrollableGraphViewDrawingLayer {

Expand Down
36 changes: 36 additions & 0 deletions graphview_example/GraphView/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class ViewController: UIViewController {
case .Dot:
addLabel(withText: "DOT")
graphView = createDotGraph(self.view.frame)
case .Bar:
addLabel(withText: "BAR")
graphView = createBarGraph(self.view.frame)
case .Pink:
addLabel(withText: "PINK")
graphView = createPinkMountainGraph(self.view.frame)
Expand Down Expand Up @@ -96,6 +99,36 @@ class ViewController: UIViewController {
return graphView
}

private func createBarGraph(frame: CGRect) -> ScrollableGraphView {
let graphView = ScrollableGraphView(frame:frame)

graphView.dataPointType = ScrollableGraphViewDataPointType.Circle
graphView.shouldDrawBarLayer = true
graphView.shouldDrawDataPoint = false

graphView.lineColor = UIColor.clearColor()
graphView.barWidth = 25
graphView.barLineWidth = 1
graphView.barLineColor = UIColor.colorFromHex("#777777")
graphView.barColor = UIColor.colorFromHex("#555555")
graphView.backgroundFillColor = UIColor.colorFromHex("#333333")

graphView.referenceLineLabelFont = UIFont.boldSystemFontOfSize(8)
graphView.referenceLineColor = UIColor.whiteColor().colorWithAlphaComponent(0.2)
graphView.referenceLineLabelColor = UIColor.whiteColor()
graphView.numberOfIntermediateReferenceLines = 5
graphView.dataPointLabelColor = UIColor.whiteColor().colorWithAlphaComponent(0.5)

graphView.shouldAnimateOnStartup = true
graphView.shouldAdaptRange = true
graphView.adaptAnimationType = ScrollableGraphViewAnimationType.Elastic
graphView.animationDuration = 1.5
graphView.rangeMax = 50
graphView.shouldRangeAlwaysStartAtZero = true

return graphView
}

private func createDotGraph(frame: CGRect) -> ScrollableGraphView {

let graphView = ScrollableGraphView(frame:frame)
Expand Down Expand Up @@ -240,12 +273,15 @@ class ViewController: UIViewController {
// The type of the current graph we are showing.
enum GraphType {
case Dark
case Bar
case Dot
case Pink

mutating func next() {
switch(self) {
case .Dark:
self = GraphType.Bar
case .Bar:
self = GraphType.Dot
case .Dot:
self = GraphType.Pink
Expand Down

0 comments on commit 23b27f2

Please sign in to comment.