如何制作从中心开始绘制并向左右扩展的UIBezierPath?
我当前的解决方案不是使用UIBezierPath,而是在另一个UIView中使用一个UIView。子视图位于其父视图的中心,当需要扩展子视图时,我会调整子视图的宽度。但是,此解决方案远非完美,因为该视图位于UIStackView内,并且堆栈视图位于UICollectionView单元中,有时无法正确获取宽度。
$_FILES
进度是double类型的类属性,设置后,我将其称为layoutIfNeeded。
我也尝试调用setNeedsLayout和layoutIfNeeded,但是它不能解决问题。 SetNeedsDisplay和invalidateIntrinzicSize也不起作用。
现在,我想使用贝塞尔曲线路径进行操作,但问题是它从给定点开始并从左向右绘制。问题是:如何使UIBezierPath居中,当我增加宽度时它会扩展(保持居中)
答案 0 :(得分:2)
有很多选择。但是这里有一些:
k
的 C = A.view(-1, *A.shape[-2:])[B.nonzero(), ...]
和CABasicAnimation
的{{1}},即:
创建strokeStart
,其strokeEnd
是最终的CAShapeLayer
(全角),但其CAShapeLayer
和path
均为0.5(即开始)半路,然后中途结束,即看不到任何东西。
UIBezierPath
然后,在strokeStart
中设置动画,将strokeEnd
更改为func configure() {
shapeLayer.strokeColor = strokeColor.cgColor
shapeLayer.lineCap = .round
setProgress(0, animated: false)
}
func updatePath() {
let path = UIBezierPath()
path.move(to: CGPoint(x: bounds.minX + lineWidth, y: bounds.midY))
path.addLine(to: CGPoint(x: bounds.maxX - lineWidth, y: bounds.midY))
shapeLayer.path = path.cgPath
shapeLayer.lineWidth = lineWidth
}
,将CABasicAnimation
更改为strokeStart
,以使动画向左移动从中间开始。例如:
0
strokeEnd
的{{1}}的动画
具有创建1
的方法:
func setProgress(_ progress: CGFloat, animated: Bool = true) {
let percent = max(0, min(1, progress))
let strokeStart = (1 - percent) / 2
let strokeEnd = 1 - (1 - percent) / 2
if animated {
let strokeStartAnimation = CABasicAnimation(keyPath: "strokeStart")
strokeStartAnimation.fromValue = shapeLayer.strokeStart
strokeStartAnimation.toValue = strokeStart
let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd")
strokeEndAnimation.fromValue = shapeLayer.strokeEnd
strokeEndAnimation.toValue = strokeEnd
let animation = CAAnimationGroup()
animation.animations = [strokeStartAnimation, strokeEndAnimation]
shapeLayer.strokeStart = strokeStart
shapeLayer.strokeEnd = strokeEnd
layer.add(animation, forKey: nil)
} else {
shapeLayer.strokeStart = strokeStart
shapeLayer.strokeEnd = strokeEnd
}
}
哪里
path
在创建CAShapeLayer
且没有动画的UIBezierPath
调用func setProgress(_ progress: CGFloat, animated: Bool = true) {
self.progress = progress
let cgPath = path(for: progress).cgPath
if animated {
let animation = CABasicAnimation(keyPath: "path")
animation.fromValue = shapeLayer.path
animation.toValue = cgPath
shapeLayer.path = cgPath
layer.add(animation, forKey: nil)
} else {
shapeLayer.path = cgPath
}
}
时;和
如果要对其进行动画处理,请调用值为func path(for progress: CGFloat) -> UIBezierPath {
let path = UIBezierPath()
let percent = max(0, min(1, progress))
let width = bounds.width - lineWidth
path.move(to: CGPoint(x: bounds.midX - width * percent / 2 , y: bounds.midY))
path.addLine(to: CGPoint(x: bounds.midX + width * percent / 2, y: bounds.midY))
return path
}
但带有动画的CAShapeLayer
。
放弃setProgress
/ 0
方法并使用setProgress
和1
基于块的动画:
使用UIBezierPath
创建简短的CAShapeLayer
,并且其图层的UIView
是视图高度的一半。
定义约束,以使视图的宽度为零。例如。您可以定义UIView
并将其放置在所需位置,并且UIView
为零。
通过将现有backgroundColor
的{{1}}设置为所需的任意宽度来对约束进行动画处理,并将cornerRadius
放置在centerXanchor
动画块中。