Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import UIKit
import PlaygroundSupport
let chartData: [Double] = [1, 2, 4, 0, 0, 2, 6, 0, 4, 8, 12, 14, 1, 2, 2, 0, 0, 1, 6, 0, 4, 0, 3, 0]
class TimelineCandleChart: UIView {
var data: [Double] = [] {
didSet { setNeedsDisplay() }
}
var candleTopColor = UIColor.cyan {
didSet { setNeedsDisplay() }
}
var candleBottomColor = UIColor.blue {
didSet { setNeedsDisplay() }
}
var candleMargin: CGFloat = 5 {
didSet { setNeedsDisplay() }
}
override func draw(_ rect: CGRect) {
guard data.count > 0 else { return }
guard let ctx = UIGraphicsGetCurrentContext() else { return }
let candleWidth: CGFloat = bounds.width / CGFloat(data.count) - candleMargin
let gradient = CGGradient(colorsSpace: nil, colors: [candleTopColor.cgColor, candleBottomColor.cgColor] as CFArray, locations: [0, 1])!
let max = data.reduce(0) { $0 < $1 ? $1 : $0 }
for i in 0..<data.count {
ctx.saveGState()
let x = (candleWidth + candleMargin) * CGFloat(i)
let height = CGFloat(data[i]) / CGFloat(max) * bounds.height
let minHeight = CGFloat.maximum(candleWidth, height)
let candleRect = CGRect(x: x, y: bounds.height - minHeight, width: candleWidth, height: minHeight)
let candlePath = UIBezierPath(roundedRect: candleRect, cornerRadius: candleWidth / 2)
ctx.addPath(candlePath.cgPath)
ctx.clip()
ctx.beginTransparencyLayer(auxiliaryInfo: nil)
ctx.drawLinearGradient(gradient, start: CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: bounds.height), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])
ctx.endTransparencyLayer()
ctx.restoreGState()
}
}
}
let chart = TimelineCandleChart()
chart.frame = CGRect(x: 0, y: 0, width: 400, height: 300)
chart.data = chartData
PlaygroundPage.current.liveView = chart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.