IHBalloonMarker.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. //
  2. // IHBalloonMarker.swift
  3. // Inhealth
  4. //
  5. // Created by weclouds on 2019/12/17.
  6. // Copyright © 2019 weclouds. All rights reserved.
  7. //
  8. import Foundation
  9. import Charts
  10. #if canImport(UIKit)
  11. import UIKit
  12. #endif
  13. open class IHBalloonMarker: MarkerImage {
  14. open var color: UIColor
  15. open var arrowSize = CGSize(width: 15, height: 11)
  16. open var font: UIFont
  17. open var textColor: UIColor
  18. open var insets: UIEdgeInsets
  19. open var minimumSize = CGSize()
  20. fileprivate var label: String?
  21. fileprivate var _labelSize: CGSize = CGSize()
  22. fileprivate var _paragraphStyle: NSMutableParagraphStyle?
  23. fileprivate var _drawAttributes = [NSAttributedString.Key : Any]()
  24. public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets)
  25. {
  26. self.color = color
  27. self.font = font
  28. self.textColor = textColor
  29. self.insets = insets
  30. _paragraphStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle
  31. _paragraphStyle?.alignment = .center
  32. super.init()
  33. }
  34. open override func offsetForDrawing(atPoint point: CGPoint) -> CGPoint
  35. {
  36. var offset = self.offset
  37. var size = self.size
  38. if size.width == 0.0 && image != nil
  39. {
  40. size.width = image!.size.width
  41. }
  42. if size.height == 0.0 && image != nil
  43. {
  44. size.height = image!.size.height
  45. }
  46. let width = size.width
  47. let height = size.height
  48. let padding: CGFloat = 8.0
  49. var origin = point
  50. origin.x -= width / 2
  51. origin.y -= height
  52. if origin.x + offset.x < 0.0
  53. {
  54. offset.x = -origin.x + padding
  55. }
  56. else if let chart = chartView,
  57. origin.x + width + offset.x > chart.bounds.size.width
  58. {
  59. offset.x = chart.bounds.size.width - origin.x - width - padding
  60. }
  61. if origin.y + offset.y < 0
  62. {
  63. offset.y = height + padding;
  64. }
  65. else if let chart = chartView,
  66. origin.y + height + offset.y > chart.bounds.size.height
  67. {
  68. offset.y = chart.bounds.size.height - origin.y - height - padding
  69. }
  70. return offset
  71. }
  72. open override func draw(context: CGContext, point: CGPoint)
  73. {
  74. guard let label = label else { return }
  75. let offset = self.offsetForDrawing(atPoint: point)
  76. let size = self.size
  77. var rect = CGRect(
  78. origin: CGPoint(
  79. x: point.x + offset.x,
  80. y: point.y + offset.y),
  81. size: size)
  82. rect.origin.x -= size.width / 2.0
  83. rect.origin.y -= size.height
  84. context.saveGState()
  85. context.setFillColor(color.cgColor)
  86. if offset.y > 0
  87. {
  88. context.beginPath()
  89. context.move(to: CGPoint(
  90. x: rect.origin.x,
  91. y: rect.origin.y + arrowSize.height))
  92. context.addLine(to: CGPoint(
  93. x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0,
  94. y: rect.origin.y + arrowSize.height))
  95. //arrow vertex
  96. context.addLine(to: CGPoint(
  97. x: point.x,
  98. y: point.y))
  99. context.addLine(to: CGPoint(
  100. x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0,
  101. y: rect.origin.y + arrowSize.height))
  102. context.addLine(to: CGPoint(
  103. x: rect.origin.x + rect.size.width,
  104. y: rect.origin.y + arrowSize.height))
  105. context.addLine(to: CGPoint(
  106. x: rect.origin.x + rect.size.width,
  107. y: rect.origin.y + rect.size.height))
  108. context.addLine(to: CGPoint(
  109. x: rect.origin.x,
  110. y: rect.origin.y + rect.size.height))
  111. context.addLine(to: CGPoint(
  112. x: rect.origin.x,
  113. y: rect.origin.y + arrowSize.height))
  114. context.fillPath()
  115. }
  116. else
  117. {
  118. context.beginPath()
  119. context.move(to: CGPoint(
  120. x: rect.origin.x,
  121. y: rect.origin.y))
  122. context.addLine(to: CGPoint(
  123. x: rect.origin.x + rect.size.width,
  124. y: rect.origin.y))
  125. context.addLine(to: CGPoint(
  126. x: rect.origin.x + rect.size.width,
  127. y: rect.origin.y + rect.size.height - arrowSize.height))
  128. context.addLine(to: CGPoint(
  129. x: rect.origin.x + (rect.size.width + arrowSize.width) / 2.0,
  130. y: rect.origin.y + rect.size.height - arrowSize.height))
  131. //arrow vertex
  132. context.addLine(to: CGPoint(
  133. x: point.x,
  134. y: point.y))
  135. context.addLine(to: CGPoint(
  136. x: rect.origin.x + (rect.size.width - arrowSize.width) / 2.0,
  137. y: rect.origin.y + rect.size.height - arrowSize.height))
  138. context.addLine(to: CGPoint(
  139. x: rect.origin.x,
  140. y: rect.origin.y + rect.size.height - arrowSize.height))
  141. context.addLine(to: CGPoint(
  142. x: rect.origin.x,
  143. y: rect.origin.y))
  144. context.fillPath()
  145. }
  146. if offset.y > 0 {
  147. rect.origin.y += self.insets.top + arrowSize.height
  148. } else {
  149. rect.origin.y += self.insets.top
  150. }
  151. rect.size.height -= self.insets.top + self.insets.bottom
  152. UIGraphicsPushContext(context)
  153. label.draw(in: rect, withAttributes: _drawAttributes)
  154. UIGraphicsPopContext()
  155. context.restoreGState()
  156. }
  157. open override func refreshContent(entry: ChartDataEntry, highlight: Highlight)
  158. {
  159. setLabel(String(entry.y))
  160. }
  161. open func setLabel(_ newLabel: String)
  162. {
  163. label = newLabel
  164. _drawAttributes.removeAll()
  165. _drawAttributes[.font] = self.font
  166. _drawAttributes[.paragraphStyle] = _paragraphStyle
  167. _drawAttributes[.foregroundColor] = self.textColor
  168. _labelSize = label?.size(withAttributes: _drawAttributes) ?? CGSize.zero
  169. var size = CGSize()
  170. size.width = _labelSize.width + self.insets.left + self.insets.right
  171. size.height = _labelSize.height + self.insets.top + self.insets.bottom
  172. size.width = max(minimumSize.width, size.width)
  173. size.height = max(minimumSize.height, size.height)
  174. self.size = size
  175. }
  176. }