公司项目 charts2.3 升到charts 3.0,marker标记报错, 然后找了很多方法, 后来用了官方看了官方的Demo终于知道该怎么做了
在charts2.3中, 用的是ChartMarker,但是在Charts3.0后就没有这个类, 替换成了MarkerView和MarkerImage, 实验了一下, 发现这两个都可以成功实现标记,而且区别不大!
上代码:MarkerView
import Foundation
import Charts
open class TBChartMarker: MarkerView
{
open var color: UIColor?
open var arrowSize = CGSize(width: 15, height: 11)
open var font: UIFont?
open var insets = UIEdgeInsets()
open var minimumSize = CGSize()
open var xAxisLabels: [String]!
open var valuesCount: Int!
fileprivate var labelns: NSString?
fileprivate var _labelSize: CGSize = CGSize()
fileprivate var _size: CGSize = CGSize()
fileprivate var _paragraphStyle: NSMutableParagraphStyle?
fileprivate var _drawAttributes = [String : AnyObject]()
public init(color: UIColor, font: UIFont, insets: UIEdgeInsets)
{
super.init(frame: CGRect())
//super.init()
//使用MarkerView时, 没有关于MarkerView init() 的方法, 这个时候会报错, 但是MarkerImage不会, 如果你可以麻烦给我说下你是怎么实现的!
self.color = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.5)
self.font = font
self.insets = insets
_paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle
_paragraphStyle?.alignment = .center
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func draw(context: CGContext, point: CGPoint)
{
if (labelns == nil)
{
return
}
var rect = CGRect(
origin: CGPoint(
// x: point.x + offset.x,
// y: point.y + offset.y),
x: point.x,
y: 40),
size: _size)
rect.origin.x -= _size.width / 2.0
rect.origin.y -= _size.height
context.saveGState()
context.setFillColor((color?.cgColor)!)
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))
context.addLine(to: CGPoint(x: rect.origin.x + rect.size.width / 2.0, y: rect.origin.y + rect.size.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))
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()
rect.origin.y += self.insets.top
rect.size.height -= self.insets.top + self.insets.bottom
UIGraphicsPushContext(context)
labelns?.draw(in: rect, withAttributes: _drawAttributes)
UIGraphicsPopContext()
context.restoreGState()
}
open override func refreshContent(entry: ChartDataEntry, highlight: Highlight)
{
let date = dateForDayOffset(valuesCount - Int(xAxisLabels[Int(entry.x)])! - 1)
let formatter = DateFormatter()
formatter.dateFormat = "MM月dd日"
let dateString = formatter.string(from: date)
let label = dateString.appending("\n\(Int(Double(entry.y.description)!))")
print("description: \(entry.y.description)")
labelns = label as NSString
_drawAttributes.removeAll()
_drawAttributes[NSFontAttributeName] = self.font
_drawAttributes[NSParagraphStyleAttributeName] = _paragraphStyle
_drawAttributes[NSForegroundColorAttributeName] = UIColor.white
_labelSize = labelns?.size(attributes: _drawAttributes) ?? CGSize.zero
_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)
}
fileprivate func dateForDayOffset(_ offset: Int) -> Date {
let date = Date()
let interval = -(offset * 60 * 60 * 24)
let offsetDate = date.addingTimeInterval(TimeInterval(interval))
return offsetDate
}
}
MarkerImage:
import Foundation
import Charts
open class TBChartMarker: MarkerImage
{
open var color: UIColor?
open var arrowSize = CGSize(width: 15, height: 11)
open var font: UIFont?
open var insets = UIEdgeInsets()
open var minimumSize = CGSize()
open var xAxisLabels: [String]!
open var valuesCount: Int!
fileprivate var labelns: NSString?
fileprivate var _labelSize: CGSize = CGSize()
fileprivate var _size: CGSize = CGSize()
fileprivate var _paragraphStyle: NSMutableParagraphStyle?
fileprivate var _drawAttributes = [String : AnyObject]()
public init(color: UIColor, font: UIFont, insets: UIEdgeInsets)
{
//super.init(frame: CGRect())
super.init()
self.color = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.5)
self.font = font
self.insets = insets
_paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle
_paragraphStyle?.alignment = .center
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint {
let size = self.size
var points = point
points.x -= size.width / 2.0
points.y -= size.height
return super.offsetForDrawing(atPoint: points)
}
open override func draw(context: CGContext, point: CGPoint)
{
if (labelns == nil)
{
return
}
var rect = CGRect(
origin: CGPoint(
// x: point.x + offset.x,
// y: point.y + offset.y),
x: point.x,
y: 40),
size: _size)
rect.origin.x -= _size.width / 2.0
rect.origin.y -= _size.height
context.saveGState()
context.setFillColor((color?.cgColor)!)
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))
context.addLine(to: CGPoint(x: rect.origin.x + rect.size.width / 2.0, y: rect.origin.y + rect.size.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))
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()
rect.origin.y += self.insets.top
rect.size.height -= self.insets.top + self.insets.bottom
UIGraphicsPushContext(context)
labelns?.draw(in: rect, withAttributes: _drawAttributes)
UIGraphicsPopContext()
context.restoreGState()
}
open override func refreshContent(entry: ChartDataEntry, highlight: Highlight)
{
let date = dateForDayOffset(valuesCount - Int(xAxisLabels[Int(entry.x)])! - 1)
let formatter = DateFormatter()
formatter.dateFormat = "MM月dd日"
let dateString = formatter.string(from: date)
let label = dateString.appending("\n\(Int(Double(entry.y.description)!))")
print("description: \(entry.y.description)")
labelns = label as NSString
_drawAttributes.removeAll()
_drawAttributes[NSFontAttributeName] = self.font
_drawAttributes[NSParagraphStyleAttributeName] = _paragraphStyle
_drawAttributes[NSForegroundColorAttributeName] = UIColor.white
_labelSize = labelns?.size(attributes: _drawAttributes) ?? CGSize.zero
_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)
}
fileprivate func dateForDayOffset(_ offset: Int) -> Date {
let date = Date()
let interval = -(offset * 60 * 60 * 24)
let offsetDate = date.addingTimeInterval(TimeInterval(interval))
return offsetDate
}
}