【发布时间】:2021-08-24 15:23:25
【问题描述】:
我有一个使用 UIBezier 路径制作的折线图。这是我的绘图功能的代码
override func draw(_ rect: CGRect) {
let width = rect.width
let height = rect.height
let path = UIBezierPath(
roundedRect: rect,
byRoundingCorners: .allCorners,
cornerRadii: Constants.cornerRadiusSize
)
path.addClip()
guard let context = UIGraphicsGetCurrentContext() else {
return
}
let colors = [startColor.cgColor, endColor.cgColor]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let colorLocations: [CGFloat] = [0.0, 1.0]
guard let gradient = CGGradient(
colorsSpace: colorSpace,
colors: colors as CFArray,
locations: colorLocations
) else {
return
}
let startPoint = CGPoint.zero
let endPoint = CGPoint(x: 0, y: bounds.height)
context.drawLinearGradient(
gradient,
start: startPoint,
end: endPoint,
options: []
)
let margin = Constants.margin
let graphWidth = width - margin * 2 - 4
let columnXPoint = { (column: Int) -> CGFloat in
// Calculate the gap between points
let spacing = graphWidth / CGFloat(self.graphPoints.count - 1)
return CGFloat(column) * spacing + margin + 2
}
let topBorder = Constants.topBorder
let bottomBorder = Constants.bottomBorder
let graphHeight = height - topBorder - bottomBorder
guard let maxValue = graphPoints.max() else {
return
}
let columnYPoint = { (graphPoint: Int) -> CGFloat in
let yPoint = CGFloat(graphPoint) / CGFloat(maxValue) * graphHeight
return graphHeight + topBorder - yPoint // Переворот графика
}
UIColor.white.setFill()
UIColor.white.setStroke()
let graphPath = UIBezierPath()
graphPath.move(to: CGPoint(x: columnXPoint(0), y: columnYPoint(graphPoints[0])))
for i in 1 ..< graphPoints.count {
let nextPoint = CGPoint(x: columnXPoint(i), y: columnYPoint(graphPoints[i]))
print(nextPoint)
graphPath.addLine(to: nextPoint)
}
self.drawAnimatedGraph(path: graphPath, rect)
context.saveGState()
guard let clippingPath = graphPath.copy() as? UIBezierPath else {
return
}
clippingPath.addLine(to: CGPoint(
x: columnXPoint(graphPoints.count - 1),
y: height))
clippingPath.addLine(to: CGPoint(x: columnXPoint(0), y: height))
clippingPath.close()
clippingPath.addClip()
let highestYPoint = columnYPoint(maxValue)
let graphStartPoint = CGPoint(x: margin, y: highestYPoint)
let graphEndPoint = CGPoint(x: margin, y: bounds.height)
context.drawLinearGradient(
gradient,
start: graphStartPoint,
end: graphEndPoint,
options: [])
context.restoreGState()
graphPath.lineWidth = 2.0
graphPath.stroke()
for i in 0 ..< graphPoints.count {
var point = CGPoint(x: columnXPoint(i), y: columnYPoint(graphPoints[i]))
point.x -= Constants.circleDiameter / 2
point.y -= Constants.circleDiameter / 2
let circle = UIBezierPath(
ovalIn: CGRect(
origin: point,
size: CGSize(
width: Constants.circleDiameter,
height: Constants.circleDiameter)
)
)
circle.fill()
}
let linePath = UIBezierPath()
linePath.move(to: CGPoint(x: margin, y: topBorder))
linePath.addLine(to: CGPoint(x: width - margin, y: topBorder))
linePath.move(to: CGPoint(x: margin, y: graphHeight / 2 + topBorder))
linePath.addLine(to: CGPoint(x: width - margin, y: graphHeight / 2 + topBorder))
linePath.move(to: CGPoint(x: margin, y: height - bottomBorder))
linePath.addLine(to: CGPoint(x: width - margin, y: height - bottomBorder))
let color = UIColor(white: 1.0, alpha: Constants.colorAlpha)
color.setStroke()
linePath.lineWidth = 1.0
linePath.stroke()
}
但我的问题是我想用动画绘制图表,我已经找到了它的代码
func drawAnimatedGraph(path: UIBezierPath, _ rect: CGRect) {
//Create a CAShape Layer
let pathLayer: CAShapeLayer = CAShapeLayer()
pathLayer.frame = self.bounds
pathLayer.path = path.cgPath
pathLayer.strokeColor = UIColor.red.cgColor
pathLayer.fillColor = nil
pathLayer.lineWidth = 2.0
pathLayer.lineJoin = CAShapeLayerLineJoin.bevel
//Add the layer to your view's layer
self.layer.addSublayer(pathLayer)
//This is basic animation, quite a few other methods exist to handle animation see the reference site answers
let pathAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
pathAnimation.duration = 2.0
pathAnimation.fromValue = 0
pathAnimation.toValue = 1
//Animation will happen right away
pathLayer.add(pathAnimation, forKey: "strokeEnd")
}
问题是我有一个计时器,它删除整数数组的第一个元素并附加随机整数。因此,当我更改数组中的数据并重绘我的图表时,它会在主图表上方绘制新图表。所以我的问题是我是否能够使用这些技术绘制动画折线图,或者我应该寻找另一种解决该问题的方法?
【问题讨论】: