簡體   English   中英

如何在iOS Swift4中創建此圓形?

[英]How I can create this circular shape in iOS Swift4?

我必須在UIView中創建如下圖所示的形狀。 但是我不知道如何繪制這種形狀。 我試圖使用帶有CAShapeLayer的UIBezierPath路徑成功繪制此形狀,但圓線繪制成功,但是我無法繪制圓點和圓形填充顏色。 任何人都可以建議我如何使用任何庫或UIBezierPath實現這種形狀。

設計圖

這是我正在嘗試繪制此圓形的代碼。

class ViewController: UIViewController {


var firstButton = UIButton()
var mylabel = UILabel()

override func viewDidLoad() {
    super.viewDidLoad()

    self.creatingLayerWithInformation()

}

func creatingLayerWithInformation(){
    let safeAreaHeight = self.view.safeAreaInsets.top
    let navBarHeight = self.navigationController?.navigationBar.frame.height

    self.addLayer(isClockWise: true, radius: self.view.frame.width * 0.72, xPoint: 0, yPoint: navBarHeight!, layerColor: UIColor.green, fillcolor: .clear)
    self.addLayer(isClockWise: true, radius: self.view.frame.width * 0.72, xPoint: self.view.frame.width, yPoint:  self.view.frame.height - 150, layerColor: UIColor.blue, fillcolor: .clear)

    let aa = self.view.frame.width * 0.72

    self.addLayer(isClockWise: true, radius: 10, xPoint: 0+aa, yPoint: navBarHeight!+5, layerColor: UIColor.blue, fillcolor: .clear)

    self.addLayer(isClockWise: true, radius: 10, xPoint: 0+15, yPoint: navBarHeight!+aa, layerColor: UIColor.blue, fillcolor: .clear)

}

func addLayer(isClockWise: Bool, radius: CGFloat, xPoint: CGFloat, yPoint: CGFloat, layerColor: UIColor, fillcolor: UIColor) {

    let pi = CGFloat(Float.pi)
    let start:CGFloat = 0.0
    let end :CGFloat = 20

    // circlecurve
    let path: UIBezierPath = UIBezierPath();
    path.addArc(
        withCenter: CGPoint(x:xPoint, y:yPoint),
        radius: (radius),
        startAngle: start,
        endAngle: end,
        clockwise: isClockWise
    )
    let layer = CAShapeLayer()
    layer.lineWidth = 3
    layer.fillColor = fillcolor.cgColor
    layer.strokeColor = layerColor.cgColor
    layer.path = path.cgPath
    self.view.layer.addSublayer(layer)
}}

但我得到以下結果。

在此處輸入圖片說明

請建議我如何實現這種形狀。 如果我做錯了什么,請糾正我。 如果有任何圖書館,也請提出建議。 請給我一些解決方案。

提前感謝大家。

有許多方法可以達到此效果,但是一個簡單的解決方案是不將大圓畫為單個弧,而是繪制為一系列在小圓的邊緣開始和停止的弧。 為此,您需要知道與內圓的偏移量。 做一點三角法,可以將其計算為:

let angleOffset = asin(innerRadius / 2 / mainRadius) * 2

從而:

let path = UIBezierPath()
path.move(to: point(from: arcCenter, radius: mainRadius, angle: startAngle))

let anglePerChoice = (endAngle - startAngle) / CGFloat(choices.count)
let angleOffset = asin(innerRadius / 2 / mainRadius) * 2
var from = startAngle
for index in 0 ..< choices.count {
    var to = from + anglePerChoice / 2 - angleOffset
    path.addArc(withCenter: arcCenter, radius: mainRadius, startAngle: from, endAngle: to, clockwise: true)
    to = from + anglePerChoice
    from += anglePerChoice / 2 + angleOffset
    path.move(to: point(from: arcCenter, radius: mainRadius, angle: from))
    path.addArc(withCenter: arcCenter, radius: mainRadius, startAngle: from, endAngle: to, clockwise: true)

    from = to
}

let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = strokeColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = lineWidth
layer.addSublayer(shapeLayer)

哪里:

func point(from point: CGPoint, radius: CGFloat, angle: CGFloat) -> CGPoint {
    return CGPoint(x: point.x + radius * cos(angle),
                   y: point.y + radius * sin(angle))
}

產生:

在此處輸入圖片說明

因此,當您添加內圓時:

在此處輸入圖片說明


盡管上面很簡單,但是它有局限性。 特別是,如果大弧線的lineWidth與小圓弧的lineWidth相比確實很寬,則單獨的大弧線的折線將無法與小圓弧的邊緣很好地對齊。 例如,想象小圓弧半徑為22點,但是大圓弧的筆划相對較寬,例如36點。

在此處輸入圖片說明

如果您有這種情況(不是您的情況,而是為了將來的讀者使用),如暗淡所建議的,另一種方法是將大圓弧繪制為單個筆觸,然后使用小圓圈的路徑對其進行遮罩。

因此,假設您有:

  • 單個CAShapeLayer ,稱為mainArcLayer ,用於大弧;

  • 所有小圓圈的UIBezierPath數組,稱為smallCirclePaths

然后,您可以在UIView子類的layoutSubviews (或UIViewController子類中的viewDidLayoutSubviews中創建掩碼,如下所示:

override func layoutSubviews() {
    super.layoutSubviews()

    let path = UIBezierPath(rect: bounds)
    smallCirclePaths.forEach { path.append($0) }

    let mask = CAShapeLayer()
    mask.fillColor = UIColor.white.cgColor
    mask.strokeColor = UIColor.clear.cgColor
    mask.lineWidth = 0
    mask.path = path.cgPath
    mask.fillRule = .evenOdd

    mainArcLayer.mask = mask
}

產生:

在此處輸入圖片說明

這是對該問題的稍微更籠統的解決方案。

以最簡單的方式考慮問題。 想象一條直線,中間有一個小圓圈。

讓我們將思維分為三層:

  • 需要顯示的背景

  • 保持直線的層

  • 包含小圓圈的圖層

計算小圓圈層相對於直線層的位置。

將小圓圈圖層放置在該位置。 好的,但是直線會顯示出來。

返回直線層。 給它戴上口罩 在小圓圈層的確切位置用透明圓圈構造該蒙版。

現在,遮罩沿着直線“打孔” —恰好是圓圈覆蓋的位置。 因此,我們似乎可以從圓環中看到背景,因為直線恰好在那個位置丟失了。

在現實生活中,將有多個圓形圖層,並且蒙版將具有多個透明圓形,並且直線將是一條曲線,但是一旦您完成了打孔操作,這將是一個小問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM