如何解决提高 CAShapeLayer 绘制的折线图的性能
我通过 CAShapeLayer
中的 MTKView
创建了一个折线图。在某些情况下,此折线图每秒更新一次,但在当前的实现中,每当图表更新(每秒)时,都会有一个微小的冻结时刻,因为它会再次绘制所有内容。我尝试了所有我能想到的方法来提高它的性能,但我无法修复它。当新数据到来时,这个冻结时刻不允许图表平滑移动。
这是我的代码的一部分:
class LineChartView: MTKView,UIScrollViewDelegate {
private let scrollView: UIScrollView = UIScrollView()
public var lineGap: CGFloat = 0.7
var dataEntries: [PointEntry]? {
didSet {
DispatchQueue.main.async {
self.setNeedsLayout()
}
}
}
private var hrDataPoints: [CGPoint]?
override func layoutSubviews() {
if let dataEntries = dataEntries {
scrollView.frame = CGRect(x: 50,y: 0,width: frame.size.width,height: frame.size.height)
scrollView.contentSize = CGSize(width: 50 + CGFloat(dataEntries.count) * lineGap,height: frame.size.height)
mainLayer.frame = CGRect(x: 0,width: CGFloat(dataEntries.count) * lineGap,height: frame.size.height)
dataLayer.frame = CGRect(x: 0,y: topSpace,width: mainLayer.frame.width,height: mainLayer.frame.height - topSpace - bottomSpace)
hrDataPoints = convertDataEntriesToPoints(entries: dataEntries)
clean()
drawCharts()
}
}
}
// MARK: - Drawing
extension LineChartView {
private func convertDataEntriesToPoints(entries: [PointEntry]) -> [CGPoint] {
if let max = entries.max()?.value,let min = entries.min()?.value {
let filteredMax = max + emptySpaceAboveAndBelowChart
let filteredMin = min - emptySpaceAboveAndBelowChart
var result: [CGPoint] = []
let minMaxRange: CGFloat = CGFloat(filteredMax - filteredMin) * topHorizontalLine
for i in 0 ..< entries.count {
let height = dataLayer.frame.height * (1 - ((CGFloat(entries[i].value) - CGFloat(filteredMin)) / minMaxRange))
let point = CGPoint(x: CGFloat(i) * lineGap + 40,y: height)
result.append(point)
}
return result
}
return []
}
private func drawCharts() {
let lineLayer = CAShapeLayer()
lineLayer.lineWidth = 2
lineLayer.fillColor = UIColor.clear.cgColor
guard let path = createPath() else { return }
lineLayer.path = path.cgPath
lineLayer.strokeColor = UIColor.green.cgColor
lineLayer.drawsAsynchronously = true
dataLayer.addSublayer(lineLayer)
}
private func createPath() -> UIBezierPath? {
var dataPoints: [CGPoint] = []
guard let points = hrDataPoints,points.count > 0 else { return nil }
dataPoints = points
let path = UIBezierPath()
path.move(to: dataPoints[0])
for i in 1 ..< dataPoints.count {
path.addLine(to: dataPoints[i])
}
return path
}
}
// MARK: - Cleaning
extension LineChartView {
private func clean() {
mainLayer.sublayers?.forEach({
if $0 is CATextLayer {
$0.removeFromSuperlayer()
}
})
gridLayer.sublayers?.forEach({ $0.removeFromSuperlayer() })
dataLayer.sublayers?.forEach({ $0.removeFromSuperlayer() })
}
}
并且在新数据到来的每一秒内,新数据都会附加到 dataEntries
中。如果有人能给我一些建议,我将不胜感激。
谢谢
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。