使用UIBezierPath实现动画动态折线图 数据更新重绘图层重叠问题咨询
解决方案
你完全不需要更换现有技术栈,只要修复图层未清理的问题即可实现带动画的动态折线图。
问题根源
图层重叠来自两个可修复的逻辑问题:
- 每次调用
drawAnimatedGraph时都会新建CAShapeLayer并添加到视图层级,从未清理旧的动画图层,这些子图层不会随draw(_ rect:)的重绘自动清除 - 原有
draw方法中既通过动画图层渲染折线,又手动调用graphPath.stroke()绘制了静态折线,二者叠加也会加重重叠问题
修改步骤
1. 新增属性存储当前动画图层
在你的自定义折线图View中新增私有属性,持有当前活跃的动画图层,方便后续清理:
private var currentGraphLayer: CAShapeLayer?
2. 优化动画绘制方法
修改drawAnimatedGraph逻辑,每次绘制前先移除旧图层,避免多层叠加,同时补充动画结束后保活的配置:
func drawAnimatedGraph(path: UIBezierPath, _ rect: CGRect) { // 移除上一次的旧动画图层 currentGraphLayer?.removeFromSuperlayer() let pathLayer = CAShapeLayer() pathLayer.frame = self.bounds pathLayer.path = path.cgPath // 可根据需求修改描边颜色,原有示例的红色和你静态折线的白色冲突,可改为和设计一致的颜色 pathLayer.strokeColor = UIColor.white.cgColor pathLayer.fillColor = nil pathLayer.lineWidth = 2.0 pathLayer.lineJoin = .bevel self.layer.addSublayer(pathLayer) // 保存新图层的引用 currentGraphLayer = pathLayer let pathAnimation = CABasicAnimation(keyPath: "strokeEnd") pathAnimation.duration = 2.0 pathAnimation.fromValue = 0 pathAnimation.toValue = 1 // 配置动画结束后保持最终状态,不会自动消失 pathAnimation.fillMode = .forwards pathAnimation.isRemovedOnCompletion = false pathLayer.add(pathAnimation, forKey: "strokeEnd") }
3. 删除冗余的静态折线绘制
找到draw方法中的graphPath.stroke()这一行代码直接删除,动画图层会负责折线的渲染,不需要重复绘制静态折线。
4. 触发重绘逻辑
每次你更新graphPoints数组(移除首元素+追加新随机数)后,调用setNeedsDisplay()即可触发重绘,不会再出现重叠问题。
原问题重叠效果参考

内容的提问来源于stack exchange,提问作者Ivanius
相关产品推荐
相关产品推荐

