如何使用 ios-charts 创建浮动图形标记
How to create a floating graph marker with ios-charts
我正在使用 ios-charts 框架,并希望创建一个标记,当我触摸并左右移动手指时,它会漂浮在图表上。我使用折线图仅供参考。
但是,当我触摸它时,我无法弄清楚如何获得图表上标记的位置。
我读过有关子类化 MarkerView 的内容,但这不起作用。你能告诉我如何获得触摸 ios-图表时显示的点的位置吗?
所以我终于让它起作用了,并想将它添加到社区中。这是我的图表:
当您 运行 将手指放在图表上时,上面的 reader 会移动并从图表中读取值。
为了让它工作,我必须执行以下操作:
在您实现图形的文件中,请务必包含
ChartViewDelegate
然后实现chartValueSelected方法。
如果您随后使用 getMarkerPosition 方法,您将能够将 "marker" 居中放置在任何您想要的位置。
下面是一些示例代码:
class MarkerView: UIView {
@IBOutlet var valueLabel: UILabel!
@IBOutlet var metricLabel: UILabel!
@IBOutlet var dateLabel: UILabel!
}
let markerView = MarkerView()
func chartValueSelected(chartView: ChartViewBase, entry: ChartDataEntry, dataSetIndex: Int, highlight: ChartHighlight) {
let graphPoint = chartView.getMarkerPosition(entry: entry, highlight: highlight)
// Adding top marker
markerView.valueLabel.text = "\(entry.value)"
markerView.dateLabel.text = "\(months[entry.xIndex])"
markerView.center = CGPointMake(graphPoint.x, markerView.center.y)
markerView.hidden = false
}
markerView
是我手动添加到还包含图形视图的主视图的 xib。 markerView
是一个包含三个标签的 UIView。就是你在图片中看到的 3.0、impressions 和 Apr。
graphPoint
是位于图上的CGPoint。您可以使用 graphPoint
的 x 和 y 来重新定位您的 markerView
。在这里,我只是保持 markerView
的 y 值不变,并更改它的 x 值,使其在触摸时来回移动。
这基于 iOS-Charts 存储库中提供的示例 BallonMarker。
希望这对某些人有用,因为我找不到 MarkerImage
的其他子 class 示例,所以这对我来说是很多线索和错误,因为我从未使用过 CGContext
之前
要使用添加这个 class
class PillMarker: MarkerImage {
private (set) var color: UIColor
private (set) var font: UIFont
private (set) var textColor: UIColor
private var labelText: String = ""
private var attrs: [NSAttributedString.Key: AnyObject]!
static let formatter: DateComponentsFormatter = {
let f = DateComponentsFormatter()
f.allowedUnits = [.minute, .second]
f.unitsStyle = .short
return f
}()
init(color: UIColor, font: UIFont, textColor: UIColor) {
self.color = color
self.font = font
self.textColor = textColor
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
attrs = [.font: font, .paragraphStyle: paragraphStyle, .foregroundColor: textColor, .baselineOffset: NSNumber(value: -4)]
super.init()
}
override func draw(context: CGContext, point: CGPoint) {
// custom padding around text
let labelWidth = labelText.size(withAttributes: attrs).width + 10
// if you modify labelHeigh you will have to tweak baselineOffset in attrs
let labelHeight = labelText.size(withAttributes: attrs).height + 4
// place pill above the marker, centered along x
var rectangle = CGRect(x: point.x, y: point.y, width: labelWidth, height: labelHeight)
rectangle.origin.x -= rectangle.width / 2.0
let spacing: CGFloat = 20
rectangle.origin.y -= rectangle.height + spacing
// rounded rect
let clipPath = UIBezierPath(roundedRect: rectangle, cornerRadius: 6.0).cgPath
context.addPath(clipPath)
context.setFillColor(UIColor.white.cgColor)
context.setStrokeColor(UIColor.black.cgColor)
context.closePath()
context.drawPath(using: .fillStroke)
// add the text
labelText.draw(with: rectangle, options: .usesLineFragmentOrigin, attributes: attrs, context: nil)
}
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
labelText = customString(entry.y)
}
private func customString(_ value: Double) -> String {
let formattedString = PillMarker.formatter.string(from: TimeInterval(value))!
// using this to convert the left axis values formatting, ie 2 min
return "\(formattedString)"
}
}
然后为您的图表激活
let marker = PillMarker(color: .white, font: UIFont.boldSystemFont(ofSize: 14), textColor: .black)
chartView.marker = marker
我正在使用 ios-charts 框架,并希望创建一个标记,当我触摸并左右移动手指时,它会漂浮在图表上。我使用折线图仅供参考。
但是,当我触摸它时,我无法弄清楚如何获得图表上标记的位置。
我读过有关子类化 MarkerView 的内容,但这不起作用。你能告诉我如何获得触摸 ios-图表时显示的点的位置吗?
所以我终于让它起作用了,并想将它添加到社区中。这是我的图表:
当您 运行 将手指放在图表上时,上面的 reader 会移动并从图表中读取值。
为了让它工作,我必须执行以下操作:
在您实现图形的文件中,请务必包含 ChartViewDelegate
然后实现chartValueSelected方法。
如果您随后使用 getMarkerPosition 方法,您将能够将 "marker" 居中放置在任何您想要的位置。
下面是一些示例代码:
class MarkerView: UIView {
@IBOutlet var valueLabel: UILabel!
@IBOutlet var metricLabel: UILabel!
@IBOutlet var dateLabel: UILabel!
}
let markerView = MarkerView()
func chartValueSelected(chartView: ChartViewBase, entry: ChartDataEntry, dataSetIndex: Int, highlight: ChartHighlight) {
let graphPoint = chartView.getMarkerPosition(entry: entry, highlight: highlight)
// Adding top marker
markerView.valueLabel.text = "\(entry.value)"
markerView.dateLabel.text = "\(months[entry.xIndex])"
markerView.center = CGPointMake(graphPoint.x, markerView.center.y)
markerView.hidden = false
}
markerView
是我手动添加到还包含图形视图的主视图的 xib。 markerView
是一个包含三个标签的 UIView。就是你在图片中看到的 3.0、impressions 和 Apr。
graphPoint
是位于图上的CGPoint。您可以使用 graphPoint
的 x 和 y 来重新定位您的 markerView
。在这里,我只是保持 markerView
的 y 值不变,并更改它的 x 值,使其在触摸时来回移动。
这基于 iOS-Charts 存储库中提供的示例 BallonMarker。
希望这对某些人有用,因为我找不到 MarkerImage
的其他子 class 示例,所以这对我来说是很多线索和错误,因为我从未使用过 CGContext
之前
要使用添加这个 class
class PillMarker: MarkerImage {
private (set) var color: UIColor
private (set) var font: UIFont
private (set) var textColor: UIColor
private var labelText: String = ""
private var attrs: [NSAttributedString.Key: AnyObject]!
static let formatter: DateComponentsFormatter = {
let f = DateComponentsFormatter()
f.allowedUnits = [.minute, .second]
f.unitsStyle = .short
return f
}()
init(color: UIColor, font: UIFont, textColor: UIColor) {
self.color = color
self.font = font
self.textColor = textColor
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
attrs = [.font: font, .paragraphStyle: paragraphStyle, .foregroundColor: textColor, .baselineOffset: NSNumber(value: -4)]
super.init()
}
override func draw(context: CGContext, point: CGPoint) {
// custom padding around text
let labelWidth = labelText.size(withAttributes: attrs).width + 10
// if you modify labelHeigh you will have to tweak baselineOffset in attrs
let labelHeight = labelText.size(withAttributes: attrs).height + 4
// place pill above the marker, centered along x
var rectangle = CGRect(x: point.x, y: point.y, width: labelWidth, height: labelHeight)
rectangle.origin.x -= rectangle.width / 2.0
let spacing: CGFloat = 20
rectangle.origin.y -= rectangle.height + spacing
// rounded rect
let clipPath = UIBezierPath(roundedRect: rectangle, cornerRadius: 6.0).cgPath
context.addPath(clipPath)
context.setFillColor(UIColor.white.cgColor)
context.setStrokeColor(UIColor.black.cgColor)
context.closePath()
context.drawPath(using: .fillStroke)
// add the text
labelText.draw(with: rectangle, options: .usesLineFragmentOrigin, attributes: attrs, context: nil)
}
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
labelText = customString(entry.y)
}
private func customString(_ value: Double) -> String {
let formattedString = PillMarker.formatter.string(from: TimeInterval(value))!
// using this to convert the left axis values formatting, ie 2 min
return "\(formattedString)"
}
}
然后为您的图表激活
let marker = PillMarker(color: .white, font: UIFont.boldSystemFont(ofSize: 14), textColor: .black)
chartView.marker = marker