在IOS中跨圆弧设置视图约束动画
我想制作一个保存进度分数的UIButton动画, 这是第一个州 我想把这个按钮动画到最后的状态 我用CAShapeLayer做了这些弧 我的代码是在IOS中跨圆弧设置视图约束动画,ios,swift,animation,Ios,Swift,Animation,我想制作一个保存进度分数的UIButton动画, 这是第一个州 我想把这个按钮动画到最后的状态 我用CAShapeLayer做了这些弧 我的代码是 let lineWidth: CGFloat = 12 let score = 90 let endAngle : CGFloat = .pi + (.pi * (CGFloat(score)/100)) let center = view.center let prog
let lineWidth: CGFloat = 12
let score = 90
let endAngle : CGFloat = .pi + (.pi * (CGFloat(score)/100))
let center = view.center
let progressPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: endAngle, clockwise: true)
endPoint = progressPath.currentPoint
let startPoint: CGPoint = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi, clockwise: true).currentPoint
let halfCirclePath = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi*2, clockwise: true)
let greyLayer = CAShapeLayer()
greyLayer.strokeColor = greyColor
greyLayer.lineWidth = lineWidth
greyLayer.path = halfCirclePath.cgPath
greyLayer.lineCap = .round
greyLayer.fillColor = UIColor.clear.cgColor
greyLayer.shadowColor = UIColor.black.cgColor
greyLayer.shadowOpacity = 1
greyLayer.shadowOffset = .zero
greyLayer.shadowRadius = 2
view.layer.addSublayer(greyLayer)
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = lineWidth
shapeLayer.path = progressPath.cgPath
shapeLayer.lineCap = .round
shapeLayer.strokeEnd = 1
shapeLayer.fillColor = UIColor.clear.cgColor
view.layer.addSublayer(shapeLayer)
let label = UILabel()
label.text = "Best"
label.textAlignment = .center
label.textColor = .red
label.font = UIFont.boldSystemFont(ofSize: 30)
view.addSubview(label)
view.layer.addSublayer(label.layer)
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
view.addSubview(scoreButton)
scoreButton.setTitle(" \(score)% ", for: .normal)
scoreButton.layer.masksToBounds = true
scoreButton.setTitleColor(.blue, for: .normal)
scoreButton.layer.shadowRadius = 8
scoreButton.layer.shadowColor = UIColor.black.cgColor
scoreButton.backgroundColor = .white
scoreButton.translatesAutoresizingMaskIntoConstraints = false
scoreButton.bottomAnchor.constraint(equalTo: view.topAnchor, constant: endPoint.y).isActive = true
scoreButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: endPoint.x).isActive = true
对于动画,我使用DispatchQueu.main.asyncAfter,但无法更改ScoreButton的约束,并且它不平滑
let frameCount:CGFloat = 100
for index in 0...Int(frameCount) {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(index)/Double(frameCount)) { [self] in
self.shapeLayer.strokeEnd = CGFloat(index )/frameCount
let currentPoint = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi + (.pi * (CGFloat(index)/frameCount)), clockwise: true).currentPoint
self.scoreButton.bottomAnchor.constraint(equalTo: self.view.topAnchor, constant: currentPoint.y).isActive = true
self.scoreButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: currentPoint.x).isActive = true
self.view.layoutIfNeeded()
}
}
发生了这个错误
[5220:309329] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x600000a20050 H:|-(114.789)-[UIButton:0x140905810' 90% '] (active, names: '|':UIView:0x140a06100 )>",
"<NSLayoutConstraint:0x600000a21270 H:|-(314)-[UIButton:0x140905810' 90% '] (active, names: '|':UIView:0x140a06100 )>"
)
[5220:309329][LayoutConstraints]无法同时满足约束。
可能下面列表中至少有一个约束是您不想要的。
试试这个:
(1) 看看每一个约束,试着找出你不期望的;
(2) 找到添加了不需要的约束的代码,然后修复它。
(
"",
""
)
是否有任何平滑的方式来设置此UIButton的动画,该按钮在动画过程中保留分数?您可以在此处设置约束
scoreButton.translatesAutoresizingMaskIntoConstraints = false
scoreButton.bottomAnchor.constraint(equalTo: view.topAnchor, constant: endPoint.y).isActive = true
scoreButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: endPoint.x).isActive = true
在这里创建另一个C冲突
let currentPoint = UIBezierPath(arcCenter: center, radius: 100, startAngle: .pi, endAngle: .pi + (.pi * (CGFloat(index)/frameCount)), clockwise: true).currentPoint
self.scoreButton.bottomAnchor.constraint(equalTo: self.view.topAnchor, constant: currentPoint.y).isActive = true
self.scoreButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: currentPoint.x).isActive = true
您需要先停用旧的,然后再添加新的,或者仅像这样更改常量
var bottomCon,leadingCon:NSLayoutConstraint?
沿弯曲路径设置视图/层动画的关键是使用关键帧动画。UIView和CALayer都支持关键帧动画 在您的情况下,应该能够使用视图水平和垂直约束的偏移常量的UIView动画 您应该能够在线找到有关使用UIView关键帧动画沿弯曲路径设置视图动画的教程 为圆弧设置动画将需要创建一个CABASICANIATION来为CAShapeLayer的strokeEnd属性设置动画。同样,网上也有关于如何做到这一点的各种教程。(我最近写了一篇关于使用这种技术制作复选标记动画的SO帖子。)Tnx:),它工作得很好,但并不平滑,有没有任何功能来制作动画和监控进度?
scoreButton.translatesAutoresizingMaskIntoConstraints = false
bottomCon = scoreButton.bottomAnchor.constraint(equalTo: view.topAnchor, constant: endPoint.y)
bottomCon.isActive = true
leadingCon = scoreButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: endPoint.x)
leadingCon.isActive = true
self.bottomCon.constant = currentPoint.y
self.leadingCon.constant = currentPoint.x
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}