1

UIBezierPath を使用して以下の円を作成しています。円の反対側に 2 つの異なる色があることに注意してください。写真の小さな長方形の上下を丸くしたいと思います。

フラットトップス

四角形 (技術的にはダッシュ) のそれぞれの上部と下部を丸くしたい。このような:

丸みを帯びたトップス

現在、私はこのコードを使用して円を作成しています:

let bounds = self.view.bounds
    let arcCenter = CGPoint(x: bounds.midX, y: bounds.midY)

    let whiteLayer = CAShapeLayer()
    let redLayer = CAShapeLayer()

    whiteLayer.fillColor = UIColor.clear.cgColor
    whiteLayer.strokeColor = UIColor.white.cgColor

    var whiteRing = UIBezierPath(arcCenter: arcCenter, radius: CGFloat(125), startAngle: 0, endAngle: CGFloat.pi, clockwise: false)
    whiteRing.rotateAroundPoint(angle: CGFloat.pi/2, center: arcCenter)
    whiteLayer.lineWidth = 10
    whiteLayer.lineDashPattern = [2, 3]
    whiteLayer.path = whiteRing.cgPath

    redLayer.fillColor = UIColor.clear.cgColor
    redLayer.strokeColor = UIColor.red.cgColor
    var redRing = UIBezierPath(arcCenter: arcCenter, radius: CGFloat(125), startAngle: 0, endAngle: CGFloat.pi, clockwise: true)
    redRing.rotateAroundPoint(angle: CGFloat.pi/2, center: arcCenter)
    redLayer.lineWidth = 10
    redLayer.lineDashPattern = [2, 3]
    redLayer.path = redRing.cgPath
    
    self.view.layer.addSublayer(whiteLayer)
   self.view.layer.addSublayer(redLayer)

これがUIBezierPathで可能かどうかは正直わかりません.CARReplicatorLayerのようなものを使用してこれを達成しようとしていましたが、各ダッシュ/白と赤の部分が重ならないように、四角形と円の 2 つの別々の部分を合わせます。2 つの異なる色を使用せずにこれを行うと、はるかに簡単になりますが、私の使用例では、2 つの異なる色が必要です。とにかくUIBezierPathでこれを行う方法はありますか?そうでない場合は、CAReplicatorLayerを使用して最初の写真の円を作成し、それぞれの小さなダッシュ/長方形が上下に丸みを帯びているようにするにはどうすればよいですか?

4

1 に答える 1

2

円形のパスをダッシュ​​するのではなく、円の中心から出ていく一連の線分をストロークします。

let center = CGPoint(x: bounds.midX, y: bounds.midY)
let path = UIBezierPath()
let maxRadius = (min(bounds.width, bounds.height) - lineWidth) / 2
let minRadius = maxRadius - tickLength + lineWidth

for i in 0 ..< tickCount {
    let angle = startAngle + (endAngle - startAngle) * CGFloat(i) / CGFloat(tickCount)
    let startPoint = center.point(at: angle, distance: minRadius)
    let endPoint = center.point(at: angle, distance: maxRadius)
    path.move(to: startPoint)
    path.addLine(to: endPoint)
}

このメソッドを使用して、これらすべての線分の始点と終点を計算します。

private extension CGPoint {
    func point(at angle: CGFloat, distance: CGFloat) -> CGPoint {
        return CGPoint(x: x + distance * cos(angle), y: y + distance * sin(angle))
    }
}

とにかく、シェイプレイヤーを作成するときに、線幅と角の丸みを適用できます。

let shapeLayer = CAShapeLayer()
shapeLayer.lineCap = .round
shapeLayer.lineWidth = lineWidth
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = ...
shapeLayer.path = path.cgPath

さて、これの問題は、赤/白のストロークの変化をアニメートしたい場合です。それを行う必要がある場合は、別の方法として、目盛りをマスクにして、その下の赤い線をアニメーション化することを検討してください。例えば

  • 背景が白のビューを作成します。
  • すべての目盛りのベジエ パスを作成します。
  • それをシェイプレイヤーで使用する
  • ビューのレイヤーのマスクをそのシェイプ レイヤーに設定します。
  • CAShapeLayer赤のパスに を追加し、アニメーション化します。

ここに画像の説明を入力

そうすれば、目盛りの角が丸くなりますが、アニメーションを実行することはできます。また、すべての目盛りのパスが 1 つになるため、目盛りの整列に関連する問題が解消されます。

于 2020-09-04T18:45:06.533 に答える