Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在iOS Swift4中创建此圆形?_Ios_Swift_Autolayout_Uibezierpath_Cashapelayer - Fatal编程技术网

如何在iOS Swift4中创建此圆形?

如何在iOS Swift4中创建此圆形?,ios,swift,autolayout,uibezierpath,cashapelayer,Ios,Swift,Autolayout,Uibezierpath,Cashapelayer,我必须在UIView中创建如下图所示的形状。但是我不知道怎么画这个形状。我正在尝试使用UIBezierPath path和CASHAPELYER绘制此形状。圆线绘制成功,但我无法绘制圆形点和圆形填充颜色。谁能建议我如何使用任何库或UIBezierPath实现此类型形状 这是我的代码,我用它来画这个圆形 class ViewController: UIViewController { var firstButton = UIButton() var mylabel = UILabel()

我必须在UIView中创建如下图所示的形状。但是我不知道怎么画这个形状。我正在尝试使用UIBezierPath path和CASHAPELYER绘制此形状。圆线绘制成功,但我无法绘制圆形点和圆形填充颜色。谁能建议我如何使用任何库或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
因此:

这将产生:

因此,当您添加内圆时:


虽然上述方法很简单,但也有局限性。特别是,如果大圆弧的
线宽
与小圆的线宽相比确实很宽,则单独的大圆弧中的断点将不会与小圆的边缘很好地对齐。例如,假设小圆圈的半径为22点,但大圆弧的笔划相对较宽,例如36点

如果你有这种情况(不是你的情况,而是为了未来的读者),另一种方法,正如马特所建议的,是把大圆弧画成一个笔划,然后用小圆的路径遮罩它

那么,想象一下你有:

  • 单个
    CAShapeLayer
    ,称为
    mainArcLayer
    ,用于大弧;及

  • 所有小圆圈的
    UIBezierPath
    数组,称为
    smallCirclePaths

然后,您可以在
UIView
子类的
layoutSubviews
中创建掩码(或者在
UIViewController
子类中创建
viewdilayoutsubviews
),如下所示:

这将产生:


对于这个问题,这是一个稍微更一般化的解决方案。

有很多方法可以达到这个效果,但一个简单的解决方案是不将大圆绘制为一个圆弧,而是绘制为一系列从小圆边缘开始和停止的圆弧。要做到这一点,您需要知道从内圈的偏移量是多少。做一点三角学,你可以计算如下:

let angleOffset = asin(innerRadius / 2 / mainRadius) * 2
因此:

这将产生:

因此,当您添加内圆时:


虽然上述方法很简单,但也有局限性。特别是,如果大圆弧的
线宽
与小圆的线宽相比确实很宽,则单独的大圆弧中的断点将不会与小圆的边缘很好地对齐。例如,假设小圆圈的半径为22点,但大圆弧的笔划相对较宽,例如36点

如果你有这种情况(不是你的情况,而是为了未来的读者),另一种方法,正如马特所建议的,是把大圆弧画成一个笔划,然后用小圆的路径遮罩它

那么,想象一下你有:

  • 大弧的单个
    CAShapeLayer
    ,称为
    mainArcLayer
    func point(from point: CGPoint, radius: CGFloat, angle: CGFloat) -> CGPoint {
        return CGPoint(x: point.x + radius * cos(angle),
                       y: point.y + radius * sin(angle))
    }
    
    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
    }