BalloonMarker.swift 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. //
  2. // BalloonMarker.swift
  3. // ChartsDemo-Swift
  4. //
  5. // Copyright 2015 Daniel Cohen Gindi & Philipp Jahoda
  6. // A port of MPAndroidChart for iOS
  7. // Licensed under Apache License 2.0
  8. //
  9. // https://github.com/danielgindi/Charts
  10. //
  11. import Foundation
  12. import Charts
  13. #if canImport(UIKit)
  14. import UIKit
  15. #endif
  16. open class BalloonMarker: MarkerImage
  17. {
  18. open var isBarchart : Bool = false
  19. open var color: UIColor
  20. open var arrowSize = CGSize(width: 0, height: 0)
  21. open var font: UIFont
  22. open var textColor: UIColor
  23. open var insets: UIEdgeInsets
  24. open var minimumSize = CGSize()
  25. fileprivate var label: String?
  26. fileprivate var _labelSize: CGSize = CGSize()
  27. fileprivate var _paragraphStyle: NSMutableParagraphStyle?
  28. fileprivate var _drawAttributes = [NSAttributedString.Key : Any]()
  29. public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets)
  30. {
  31. self.color = color
  32. self.font = font
  33. self.textColor = textColor
  34. self.insets = insets
  35. _paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle
  36. _paragraphStyle?.alignment = .center
  37. super.init()
  38. }
  39. var leftView: UIView?
  40. var rightView: UIView?
  41. var circleView:UIView?
  42. open override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
  43. {
  44. var offset = self.offset
  45. var size = self.size
  46. if size.width == 0.0 && image != nil
  47. {
  48. size.width = image!.size.width
  49. }
  50. if size.height == 0.0 && image != nil
  51. {
  52. size.height = image!.size.height
  53. }
  54. let width = size.width
  55. let height = size.height
  56. let padding: CGFloat = 8.0
  57. var origin = point
  58. origin.x -= width / 2
  59. origin.y = 0
  60. if origin.x + offset.x < 0.0
  61. {
  62. offset.x = -origin.x + padding
  63. }
  64. else if let chart = chartView,
  65. origin.x + width + offset.x > chart.bounds.size.width
  66. {
  67. offset.x = chart.bounds.size.width - origin.x - width - padding
  68. }
  69. if origin.y + offset.y < 0
  70. {
  71. // offset.y = height + padding;
  72. }
  73. else if let chart = chartView,
  74. origin.y + height + offset.y > chart.bounds.size.height
  75. {
  76. // offset.y = chart.bounds.size.height - origin.y - height - padding
  77. }
  78. return offset
  79. }
  80. open override func draw(context: CGContext, point: CGPoint)
  81. {
  82. guard let label = label else { return }
  83. let offset = self.offsetForDrawing(atPoint: point)
  84. let size = self.size
  85. var rect = CGRect(
  86. origin: CGPoint(
  87. x: point.x + offset.x,
  88. y: point.y + offset.y),
  89. size: size)
  90. rect.origin.x -= size.width / 2.0
  91. rect.origin.y = 0
  92. // if isBarchart == true {
  93. if circleView == nil {
  94. circleView = UIView()
  95. chartView?.addSubview(circleView!)
  96. circleView?.backgroundColor = .white
  97. circleView?.layer.masksToBounds = true
  98. circleView?.layer.cornerRadius = 5
  99. circleView?.layer.borderWidth = 2
  100. circleView?.layer.borderColor = UIColor(hexString: "#573F95").cgColor
  101. }
  102. circleView?.frame = CGRect(x: point.x - 5, y: point.y - 5, width: 10, height: 10)
  103. //}
  104. context.saveGState()
  105. context.setFillColor(color.cgColor)
  106. // if offset.y > 0
  107. // {
  108. // context.beginPath()
  109. // context.move(to: CGPoint(
  110. // x: rect.origin.x,
  111. // y: rect.origin.y + arrowSize.height))
  112. // context.addLine(to: CGPoint(
  113. // x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0,
  114. // y: rect.origin.y + arrowSize.height))
  115. // //arrow vertex
  116. // context.addLine(to: CGPoint(
  117. // x: point.x,
  118. // y: point.y))
  119. // context.addLine(to: CGPoint(
  120. // x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0,
  121. // y: rect.origin.y + arrowSize.height))
  122. // context.addLine(to: CGPoint(
  123. // x: rect.origin.x + rect.size.width,
  124. // y: rect.origin.y + arrowSize.height))
  125. // context.addLine(to: CGPoint(
  126. // x: rect.origin.x + rect.size.width,
  127. // y: rect.origin.y + rect.size.height))
  128. // context.addLine(to: CGPoint(
  129. // x: rect.origin.x,
  130. // y: rect.origin.y + rect.size.height))
  131. // context.addLine(to: CGPoint(
  132. // x: rect.origin.x,
  133. // y: rect.origin.y + arrowSize.height))
  134. // context.fillPath()
  135. // }
  136. // else
  137. // {
  138. context.beginPath()
  139. context.move(to: CGPoint(
  140. x: rect.origin.x,
  141. y: rect.origin.y))
  142. context.addLine(to: CGPoint(
  143. x: rect.origin.x + rect.size.width,
  144. y: rect.origin.y))
  145. context.addLine(to: CGPoint(
  146. x: rect.origin.x + rect.size.width,
  147. y: rect.origin.y + rect.size.height - arrowSize.height))
  148. context.addLine(to: CGPoint(
  149. x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0,
  150. y: rect.origin.y + rect.size.height - arrowSize.height))
  151. //arrow vertex
  152. context.addLine(to: CGPoint(
  153. x: point.x,
  154. y: point.y))
  155. context.addLine(to: CGPoint(
  156. x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0,
  157. y: rect.origin.y + rect.size.height - arrowSize.height))
  158. context.addLine(to: CGPoint(
  159. x: rect.origin.x,
  160. y: rect.origin.y + rect.size.height - arrowSize.height))
  161. context.addLine(to: CGPoint(
  162. x: rect.origin.x,
  163. y: rect.origin.y))
  164. context.fillPath()
  165. rect.origin.y += self.insets.top
  166. rect.size.height -= self.insets.top + self.insets.bottom
  167. UIGraphicsPushContext(context)
  168. label.draw(in: rect, withAttributes: _drawAttributes)
  169. UIGraphicsPopContext()
  170. context.restoreGState()
  171. if leftView == nil {
  172. leftView = UIView()
  173. chartView?.addSubview(leftView!)
  174. }
  175. leftView?.backgroundColor = UIColor(hexString: "#FFFFFF", transparency: 0.60)
  176. leftView?.frame = CGRect(x: 0, y: 0, width: rect.origin.x, height: (chartView?.bounds.size.height)!)
  177. if rightView == nil {
  178. rightView = UIView()
  179. chartView?.addSubview(rightView!)
  180. }
  181. rightView?.backgroundColor = UIColor(hexString: "#FFFFFF", transparency: 0.60)
  182. rightView!.frame = CGRect(x: rect.origin.x + rect.size.width, y: 0, width: (chartView?.bounds.size.width)! - rect.origin.x - rect.size.width, height: (chartView?.bounds.size.height)!)
  183. }
  184. open override func refreshContent(entry: ChartDataEntry, highlight: Highlight)
  185. {
  186. setLabel(String(entry.y))
  187. }
  188. open func setLabel(_ newLabel: String)
  189. {
  190. label = newLabel
  191. _drawAttributes.removeAll()
  192. _drawAttributes[.font] = self.font
  193. _drawAttributes[.paragraphStyle] = _paragraphStyle
  194. _drawAttributes[.foregroundColor] = self.textColor
  195. _labelSize = label?.size(withAttributes: _drawAttributes) ?? CGSize.zero
  196. var size = CGSize()
  197. size.width = _labelSize.width + self.insets.left + self.insets.right
  198. size.height = _labelSize.height + self.insets.top + self.insets.bottom
  199. size.width = max(minimumSize.width, size.width)
  200. size.height = max(minimumSize.height, size.height)
  201. self.size = size
  202. }
  203. }