如何在 ios-图表上添加标记?
How can I add a Marker on ios-charts?
我正在使用 Objective-C 创建一个 iOS 应用程序,我需要使用 ios-charts。
现在我遇到了一个问题,我找不到将标记添加到我的 graphView 的方法。
此外,我需要通过用户操作更改 YAxis 数据集,但我不知道如何实现此功能。
感谢您的帮助。
首先,一次一个问题。不要一口气问两个不相关的问题 post.
ios-charts 有 ChartMarker
class 添加自定义标记。
ChartsDemo中有演示代码:
BalloonMarker *marker = [[BalloonMarker alloc] initWithColor:[UIColor colorWithWhite:180/255. alpha:1.0] font:[UIFont systemFontOfSize:12.0] insets: UIEdgeInsetsMake(8.0, 8.0, 20.0, 8.0)];
marker.minimumSize = CGSizeMake(80.f, 40.f);
_chartView.marker = marker;
您也可以编写自己的标记。看一下代码。它还可以绘制图像而不是文本。
如果您想更改数据条目,只需通过 addEntry
将新条目添加到数据集中并调用 notifyDataSetChanged
,或者 re-create 一个新的图表数据(可能有性能问题)
你真的应该首先尝试在 github 页面或 SO 上搜索旧问题,因为你的问题只是重复的问题。
您只需实施 IChartMarker 或从演示中导入 swift class。
我正在使用一个 objective-c 项目,所以为了理智,我在 objective-c 中实现了 IChartMarker,我将其作为要点提出。我已将其作为将来遇到此问题的人的要点。它相当基础,因此您可能需要对其进行修改。
https://gist.github.com/jakehoskins/8d668688f62fa93ecf8bf7921428c53f
在 Charts->Components
文件夹中添加此代码和此 BalloonMarker class:
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
//气球标记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
}
}
不幸的是,图书馆本身没有 class 显示带文本的标记。 github 上提供的示例中有此 BalloonMarker class,但它未包含在库中。因此,您可以使用 github 示例中的 BalloonMarker,或者下面是您可以使用的另一个简单标记 class。我认为它可能比 BallonMarker 更容易理解和定制:
class ChartMarker: MarkerView {
var text = ""
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
super.refreshContent(entry: entry, highlight: highlight)
text = String(entry.y)
}
override func draw(context: CGContext, point: CGPoint) {
super.draw(context: context, point: point)
var drawAttributes = [NSAttributedStringKey : Any]()
drawAttributes[.font] = UIFont.systemFont(ofSize: 15)
drawAttributes[.foregroundColor] = UIColor.white
drawAttributes[.backgroundColor] = UIColor.darkGray
self.bounds.size = (" \(text) " as NSString).size(withAttributes: drawAttributes)
self.offset = CGPoint(x: 0, y: -self.bounds.size.height - 2)
let offset = self.offsetForDrawing(atPoint: point)
drawText(text: " \(text) " as NSString, rect: CGRect(origin: CGPoint(x: point.x + offset.x, y: point.y + offset.y), size: self.bounds.size), withAttributes: drawAttributes)
}
func drawText(text: NSString, rect: CGRect, withAttributes attributes: [NSAttributedStringKey : Any]? = nil) {
let size = text.size(withAttributes: attributes)
let centeredRect = CGRect(x: rect.origin.x + (rect.size.width - size.width) / 2.0, y: rect.origin.y + (rect.size.height - size.height) / 2.0, width: size.width, height: size.height)
text.draw(in: centeredRect, withAttributes: attributes)
}
}
并将其与给定图表一起使用:
let marker = ChartMarker()
marker.chartView = chartView
chartView.marker = marker
基于,引入了ChartMarker
class。我已将其更新为 Swift 5 并进行了清理,减少了不必要的分配并提高了可读性。
class ChartMarker: MarkerView {
private var text = String()
private let drawAttributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 15),
.foregroundColor: UIColor.white,
.backgroundColor: UIColor.darkGray
]
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
text = String(entry.y)
}
override func draw(context: CGContext, point: CGPoint) {
super.draw(context: context, point: point)
let sizeForDrawing = text.size(withAttributes: drawAttributes)
bounds.size = sizeForDrawing
offset = CGPoint(x: -sizeForDrawing.width / 2, y: -sizeForDrawing.height - 4)
let offset = offsetForDrawing(atPoint: point)
let originPoint = CGPoint(x: point.x + offset.x, y: point.y + offset.y)
let rectForText = CGRect(origin: originPoint, size: sizeForDrawing)
drawText(text: text, rect: rectForText, withAttributes: drawAttributes)
}
private func drawText(text: String, rect: CGRect, withAttributes attributes: [NSAttributedString.Key: Any]? = nil) {
let size = bounds.size
let centeredRect = CGRect(
x: rect.origin.x + (rect.size.width - size.width) / 2,
y: rect.origin.y + (rect.size.height - size.height) / 2,
width: size.width,
height: size.height
)
text.draw(in: centeredRect, withAttributes: attributes)
}
}
用法:
let marker = ChartMarker()
marker.chartView = chartView
chartView.marker = marker
我正在使用 Objective-C 创建一个 iOS 应用程序,我需要使用 ios-charts。
现在我遇到了一个问题,我找不到将标记添加到我的 graphView 的方法。
此外,我需要通过用户操作更改 YAxis 数据集,但我不知道如何实现此功能。
感谢您的帮助。
首先,一次一个问题。不要一口气问两个不相关的问题 post.
ios-charts 有 ChartMarker
class 添加自定义标记。
ChartsDemo中有演示代码:
BalloonMarker *marker = [[BalloonMarker alloc] initWithColor:[UIColor colorWithWhite:180/255. alpha:1.0] font:[UIFont systemFontOfSize:12.0] insets: UIEdgeInsetsMake(8.0, 8.0, 20.0, 8.0)];
marker.minimumSize = CGSizeMake(80.f, 40.f);
_chartView.marker = marker;
您也可以编写自己的标记。看一下代码。它还可以绘制图像而不是文本。
如果您想更改数据条目,只需通过 addEntry
将新条目添加到数据集中并调用 notifyDataSetChanged
,或者 re-create 一个新的图表数据(可能有性能问题)
你真的应该首先尝试在 github 页面或 SO 上搜索旧问题,因为你的问题只是重复的问题。
您只需实施 IChartMarker 或从演示中导入 swift class。
我正在使用一个 objective-c 项目,所以为了理智,我在 objective-c 中实现了 IChartMarker,我将其作为要点提出。我已将其作为将来遇到此问题的人的要点。它相当基础,因此您可能需要对其进行修改。
https://gist.github.com/jakehoskins/8d668688f62fa93ecf8bf7921428c53f
在 Charts->Components
文件夹中添加此代码和此 BalloonMarker class:
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
//气球标记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
}
}
不幸的是,图书馆本身没有 class 显示带文本的标记。 github 上提供的示例中有此 BalloonMarker class,但它未包含在库中。因此,您可以使用 github 示例中的 BalloonMarker,或者下面是您可以使用的另一个简单标记 class。我认为它可能比 BallonMarker 更容易理解和定制:
class ChartMarker: MarkerView {
var text = ""
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
super.refreshContent(entry: entry, highlight: highlight)
text = String(entry.y)
}
override func draw(context: CGContext, point: CGPoint) {
super.draw(context: context, point: point)
var drawAttributes = [NSAttributedStringKey : Any]()
drawAttributes[.font] = UIFont.systemFont(ofSize: 15)
drawAttributes[.foregroundColor] = UIColor.white
drawAttributes[.backgroundColor] = UIColor.darkGray
self.bounds.size = (" \(text) " as NSString).size(withAttributes: drawAttributes)
self.offset = CGPoint(x: 0, y: -self.bounds.size.height - 2)
let offset = self.offsetForDrawing(atPoint: point)
drawText(text: " \(text) " as NSString, rect: CGRect(origin: CGPoint(x: point.x + offset.x, y: point.y + offset.y), size: self.bounds.size), withAttributes: drawAttributes)
}
func drawText(text: NSString, rect: CGRect, withAttributes attributes: [NSAttributedStringKey : Any]? = nil) {
let size = text.size(withAttributes: attributes)
let centeredRect = CGRect(x: rect.origin.x + (rect.size.width - size.width) / 2.0, y: rect.origin.y + (rect.size.height - size.height) / 2.0, width: size.width, height: size.height)
text.draw(in: centeredRect, withAttributes: attributes)
}
}
并将其与给定图表一起使用:
let marker = ChartMarker()
marker.chartView = chartView
chartView.marker = marker
基于ChartMarker
class。我已将其更新为 Swift 5 并进行了清理,减少了不必要的分配并提高了可读性。
class ChartMarker: MarkerView {
private var text = String()
private let drawAttributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 15),
.foregroundColor: UIColor.white,
.backgroundColor: UIColor.darkGray
]
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
text = String(entry.y)
}
override func draw(context: CGContext, point: CGPoint) {
super.draw(context: context, point: point)
let sizeForDrawing = text.size(withAttributes: drawAttributes)
bounds.size = sizeForDrawing
offset = CGPoint(x: -sizeForDrawing.width / 2, y: -sizeForDrawing.height - 4)
let offset = offsetForDrawing(atPoint: point)
let originPoint = CGPoint(x: point.x + offset.x, y: point.y + offset.y)
let rectForText = CGRect(origin: originPoint, size: sizeForDrawing)
drawText(text: text, rect: rectForText, withAttributes: drawAttributes)
}
private func drawText(text: String, rect: CGRect, withAttributes attributes: [NSAttributedString.Key: Any]? = nil) {
let size = bounds.size
let centeredRect = CGRect(
x: rect.origin.x + (rect.size.width - size.width) / 2,
y: rect.origin.y + (rect.size.height - size.height) / 2,
width: size.width,
height: size.height
)
text.draw(in: centeredRect, withAttributes: attributes)
}
}
用法:
let marker = ChartMarker()
marker.chartView = chartView
chartView.marker = marker