

(2)样例代码
import UIKit
import Charts
class ViewController: UIViewController, ChartViewDelegate {
//折线图
var chartView: LineChartView!
override func viewDidLoad() {
super.viewDidLoad()
//创建折线图组件对象
chartView = LineChartView()
chartView.frame = CGRect(x: 20, y: 80, width: self.view.bounds.width - 40,
height: 270)
chartView.delegate = self //设置代理
self.view.addSubview(chartView)
//生成10条随机数据
var dataEntries = [ChartDataEntry]()
for i in 0..<10 {
let y = arc4random()%100
let entry = ChartDataEntry.init(x: Double(i), y: Double(y))
dataEntries.append(entry)
}
//这10条数据作为1根折线里的所有数据
let chartDataSet = LineChartDataSet(values: dataEntries, label: "图例1")
//目前折线图只包括1根折线
let chartData = LineChartData(dataSets: [chartDataSet])
//设置折线图数据
chartView.data = chartData
}
//折线上的点选中回调
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry,
highlight: Highlight) {
print("选中了一个数据")
//显示该点的MarkerView标签
self.showMarkerView(value: "\(entry.y)")
}
//显示MarkerView标签
func showMarkerView(value:String){
let marker = MarkerView(frame: CGRect(x: 20, y: 20, width: 80, height: 20))
marker.chartView = self.chartView
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 80, height: 20))
label.text = "数据:\(value)"
label.textColor = UIColor.white
label.font = UIFont.systemFont(ofSize: 12)
label.backgroundColor = UIColor.gray
label.textAlignment = .center
marker.addSubview(label)
self.chartView.marker = marker
}
//折线上的点取消选中回调
func chartValueNothingSelected(_ chartView: ChartViewBase) {
print("取消选中的数据")
}
//图表通过手势缩放后的回调
func chartScaled(_ chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) {
print("图表缩放了")
}
//图表通过手势拖动后的回调
func chartTranslated(_ chartView: ChartViewBase, dX: CGFloat, dY: CGFloat) {
print("图表移动了")
}
}


import Foundation
import Charts
open class BalloonMarker: MarkerImage
{
open var color: UIColor
open var arrowSize = CGSize(width: 15, height: 11)
open var font: UIFont
open var textColor: UIColor
open var insets: UIEdgeInsets
open var minimumSize = CGSize()
fileprivate var label: String?
fileprivate var _labelSize: CGSize = CGSize()
fileprivate var _paragraphStyle: NSMutableParagraphStyle?
fileprivate var _drawAttributes = [NSAttributedStringKey : AnyObject]()
public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets)
{
self.color = color
self.font = font
self.textColor = textColor
self.insets = insets
_paragraphStyle = NSParagraphStyle.default.mutableCopy()
as? NSMutableParagraphStyle
_paragraphStyle?.alignment = .center
super.init()
}
open override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
{
var offset = self.offset
var size = self.size
if size.width == 0.0 && image != nil
{
size.width = image!.size.width
}
if size.height == 0.0 && image != nil
{
size.height = image!.size.height
}
let width = size.width
let height = size.height
let padding: CGFloat = 8.0
var origin = point
origin.x -= width / 2
origin.y -= height
if origin.x + offset.x < 0.0
{
offset.x = -origin.x + padding
}
else if let chart = chartView,
origin.x + width + offset.x > chart.bounds.size.width
{
offset.x = chart.bounds.size.width - origin.x - width - padding
}
if origin.y + offset.y < 0
{
offset.y = height + padding;
}
else if let chart = chartView,
origin.y + height + offset.y > chart.bounds.size.height
{
offset.y = chart.bounds.size.height - origin.y - height - padding
}
return offset
}
open override func draw(context: CGContext, point: CGPoint)
{
guard let label = label else { return }
let offset = self.offsetForDrawing(atPoint: point)
let size = self.size
var rect = CGRect(
origin: CGPoint(
x: point.x + offset.x,
y: point.y + offset.y),
size: size)
rect.origin.x -= size.width / 2.0
rect.origin.y -= size.height
context.saveGState()
context.setFillColor(color.cgColor)
if offset.y > 0
{
context.beginPath()
context.move(to: CGPoint(
x: rect.origin.x,
y: rect.origin.y + arrowSize.height))
context.addLine(to: CGPoint(
x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0,
y: rect.origin.y + arrowSize.height))
//arrow vertex
context.addLine(to: CGPoint(
x: point.x,
y: point.y))
context.addLine(to: CGPoint(
x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0,
y: rect.origin.y + arrowSize.height))
context.addLine(to: CGPoint(
x: rect.origin.x + rect.size.width,
y: rect.origin.y + arrowSize.height))
context.addLine(to: CGPoint(
x: rect.origin.x + rect.size.width,
y: rect.origin.y + rect.size.height))
context.addLine(to: CGPoint(
x: rect.origin.x,
y: rect.origin.y + rect.size.height))
context.addLine(to: CGPoint(
x: rect.origin.x,
y: rect.origin.y + arrowSize.height))
context.fillPath()
}
else
{
context.beginPath()
context.move(to: CGPoint(
x: rect.origin.x,
y: rect.origin.y))
context.addLine(to: CGPoint(
x: rect.origin.x + rect.size.width,
y: rect.origin.y))
context.addLine(to: CGPoint(
x: rect.origin.x + rect.size.width,
y: rect.origin.y + rect.size.height - arrowSize.height))
context.addLine(to: CGPoint(
x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0,
y: rect.origin.y + rect.size.height - arrowSize.height))
//arrow vertex
context.addLine(to: CGPoint(
x: point.x,
y: point.y))
context.addLine(to: CGPoint(
x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0,
y: rect.origin.y + rect.size.height - arrowSize.height))
context.addLine(to: CGPoint(
x: rect.origin.x,
y: rect.origin.y + rect.size.height - arrowSize.height))
context.addLine(to: CGPoint(
x: rect.origin.x,
y: rect.origin.y))
context.fillPath()
}
if offset.y > 0 {
rect.origin.y += self.insets.top + arrowSize.height
} else {
rect.origin.y += self.insets.top
}
rect.size.height -= self.insets.top + self.insets.bottom
UIGraphicsPushContext(context)
label.draw(in: rect, withAttributes: _drawAttributes)
UIGraphicsPopContext()
context.restoreGState()
}
/**
open override func refreshContent(entry: ChartDataEntry, highlight: Highlight)
{
setLabel(String(entry.y))
}
**/
open func setLabel(_ newLabel: String)
{
label = newLabel
_drawAttributes.removeAll()
_drawAttributes[.font] = self.font
_drawAttributes[.paragraphStyle] = _paragraphStyle
_drawAttributes[.foregroundColor] = self.textColor
_labelSize = label?.size(withAttributes: _drawAttributes) ?? CGSize.zero
var size = CGSize()
size.width = _labelSize.width + self.insets.left + self.insets.right
size.height = _labelSize.height + self.insets.top + self.insets.bottom
size.width = max(minimumSize.width, size.width)
size.height = max(minimumSize.height, size.height)
self.size = size
}
}

//显示MarkerView标签
func showMarkerView(value:String){
//使用气泡状的标签
let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1),
font: .systemFont(ofSize: 12),
textColor: .white,
insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8))
marker.chartView = self.chartView
marker.minimumSize = CGSize(width: 80, height: 40)
marker.setLabel("数据:\(value)")
self.chartView.marker = marker
}
