如何使UIBezierPath从中心填充

时间:2019-07-01 20:02:12

标签: ios swift uibezierpath cashapelayer

如何制作从中心开始绘制并向左右扩展的UIBezierPath?

我当前的解决方案不是使用UIBezierPath,而是在另一个UIView中使用一个UIView。子视图位于其父视图的中心,当需要扩展子视图时,我会调整子视图的宽度。但是,此解决方案远非完美,因为该视图位于UIStackView内,并且堆栈视图位于UICollectionView单元中,有时无法正确获取宽度。

$_FILES

进度是double类型的类属性,设置后,我将其称为layoutIfNeeded。

我也尝试调用setNeedsLayout和layoutIfNeeded,但是它不能解决问题。 SetNeedsDisplay和invalidateIntrinzicSize也不起作用。

现在,我想使用贝塞尔曲线路径进行操作,但问题是它从给定点开始并从左向右绘制。问题是:如何使UIBezierPath居中,当我增加宽度时它会扩展(保持居中)

这是我想要实现的目标。 enter image description here

1 个答案:

答案 0 :(得分:2)

有很多选择。但是这里有一些:

    k
  1. C = A.view(-1, *A.shape[-2:])[B.nonzero(), ...] CABasicAnimation的{​​{1}},即:

    • 创建strokeStart,其strokeEnd是最终的CAShapeLayer(全角),但其CAShapeLayerpath均为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
  2. 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

  3. 放弃setProgress / 0方法并使用setProgress1基于块的动画:

    • 使用UIBezierPath创建简短的CAShapeLayer,并且其图层的UIView是视图高度的一半。

    • 定义约束,以使视图的宽度为零。例如。您可以定义UIView并将其放置在所需位置,并且UIView为零。

    • 通过将现有backgroundColor的{​​{1}}设置为所需的任意宽度来对约束进行动画处理,并将cornerRadius放置在centerXanchor动画块中。