Search code examples
iosobjective-cios-charts

How can I add a Marker on ios-charts?


I'm creating an iOS app using Objective-C and I need to use ios-charts.

Now I'm facing a problem that I couldn't find the way to add a Marker to my graphView.

Also, I need to change the YAxis data set by user action, but I have no idea how to implement this feature.

Thank you for your help.


Solution

  • Add this code and this BalloonMarker class in the Charts->Components folder:

    var charts = LineChartView()
    
    let marker:BalloonMarker = BalloonMarker(color: UIColor(red: 93/255, green: 186/255, blue: 215/255, alpha: 1), font: UIFont(name: "Helvetica", size: 12)!, textColor: UIColor.white, insets: UIEdgeInsets(top: 7.0, left: 7.0, bottom: 25.0, right: 7.0))
     marker.minimumSize = CGSize(width: 75.0, height: 35.0)//CGSize(75.0, 35.0)
    charts.marker = marker
    

    //BalloonMarker class

    import Foundation
    import CoreGraphics
    import UIKit
    
    
    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 = [String : AnyObject]()
    
        public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets)
        {
            super.init()
    
            self.color = color
            self.font = font
            self.textColor = textColor
            self.insets = insets
    
            _paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle
            _paragraphStyle?.alignment = .center
        }
    
        open override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
        {
            let size = self.size
            var point = point
            point.x -= size.width / 2.0
            point.y -= size.height
            return super.offsetForDrawing(atPoint: point)
        }
    
        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()
    
            if let color = color
            {
                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)
    
            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[NSFontAttributeName] = self.font
            _drawAttributes[NSParagraphStyleAttributeName] = _paragraphStyle
            _drawAttributes[NSForegroundColorAttributeName] = self.textColor
    
            _labelSize = label?.size(attributes: _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
        }
    }