gpt4 book ai didi

ios - 使用UIBezierPath绘制同心圆

转载 作者:行者123 更新时间:2023-12-01 15:57:36 31 4
gpt4 key购买 nike

我正在尝试使用UIBezierPath绘制同心圆,如此image所示。

但是我实际上得到的是不同的像this

我试图制作两个不同直径的圆形并填充较小的圆形。

  let path = UIBezierPath(ovalIn: CGRect(x: position.x - diameter / 2, y: position.y - diameter / 2, width: diameter, height: diameter))
let path2 = UIBezierPath(ovalIn: CGRect(x: position.x - diameter / 2 + 2, y: position.y - diameter / 2 + 2, width: diameter - 2, height: diameter - 2))


let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = color.cgColor
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.lineWidth = lineWidth

let shapeLayer2 = CAShapeLayer()
shapeLayer.path = path2.cgPath
shapeLayer.strokeColor = color.cgColor
shapeLayer.fillColor = isFilled ? color.cgColor : UIColor.white.cgColor
shapeLayer.lineWidth = lineWidth


view.layer.addSublayer(shapeLayer)
view.layer.addSublayer(shapeLayer2)

最佳答案

这就是使用图层的方法。

使用图层而不是绘制图层确实有很多优点。

(通过“绘制”,我的意思是在draw#rect中绘制它。)

从动画开始比较容易。而且更可重用;而您不必担心“如果视图移动/重塑我应该重画什么”的困难。一切都是自动的。

因此,在制作图层时,这是的四个主要工作:

1.与往常一样,制作图层,然后在layoutSubviews中设置其框架。

在iOS中,当您制作图层时,您(A)将设置为(几乎可以肯定是 lazy var ),而将(B)设置为
时是(B),当然,您设置框架的大小。

这些是在iOS中使用图层的两个基本步骤。

请注意,您请勿在布局时将其设置为您,而请勿在启动时设置框架。您仅在启动时制作它们,并且仅在布局时设置框架的大小。

我在情节提要中制作了一个UIView,“Thingy”,并使用约束将其定位为100x100。

我将背景色设为蓝色,以便您可以看到发生了什么。 (您可能希望它清楚一点。)

enter image description here

它在应用程序中:

enter image description here

我们将需要环的厚度和间隙:

class Thingy: UIView {

var thicknessOfOuterRing: CGFloat = 20.0 {
didSet{ setNeedsLayout() }
}

var thicknessOfTheGap: CGFloat = 20.0 {
didSet{ setNeedsLayout() }
}

要理解的一个关键点是,当您更改这些值时,必须调整所有内容的大小。对?

这意味着您可以按照通常的方式将“didSet .. setNeedsLayout”添加到这些属性中。

(类似地,如果您想即时更改颜色,也可以对颜色进行更改。想要“更改”的任何内容,都需要“didSet .. setNeedsLayout”模式。 )

我们将始终需要两个简单的计算,即半厚度和它们的组合脂肪。只需对它们使用计算变量,即可大大简化您的代码。
var halfT: CGFloat { return thicknessOfOuterRing / 2.0 }
var both: CGFloat { return thicknessOfOuterRing + thicknessOfTheGap }

好!有两层。圆环将是一个形状图层,但中间的斑点可以只是一个图层:
private lazy var outerBand: CAShapeLayer = {
let l = CAShapeLayer()
layer.addSublayer(l)
return l
}()

private lazy var centralBlob: CALayer = {
let l = CALayer()
layer.addSublayer(l)
return l
}()

当然,现在,您必须在布局时设置其框架:
override func layoutSubviews() {
super.layoutSubviews()

outerBand.frame = bounds
centralBlob.frame = bounds
}

这就是在iOS中使用图层的基本过程。

(A)在布局时制作图层(几乎可以肯定是使用惰性变量)和(B),当然,您可以设置框架的大小。

2.在制作完图层后,设置它们的所有“固定”方面:

永不更改的图层质量是什么?

在惰性变量中设置那些“不变”的质量:
private lazy var outerBand: CAShapeLayer = {
let l = CAShapeLayer()
l.fillColor = UIColor.clear.cgColor
l.strokeColor = UIColor.black.cgColor
layer.addSublayer(l)
return l
}()

private lazy var centralBlob: CALayer = {
let l = CALayer()
l.backgroundColor = UIColor.black.cgColor
layer.addSublayer(l)
return l
}()

再一次,的任何内容都不会改变,请将其推入懒惰的变量中。

下一个 ...

3.在布局中设置图层的所有“更改”方面:

关于中央斑点。在iOS中使用正方形CALayer制作硬币形状非常容易,您只需执行以下操作:
someCALayer.cornerRadius = someCALayer.bounds.width / 2.0

请注意,您可能会和某些程序员一起使用,实际上是使用形状图层,然后再去制作圆形形状等等。但是,仅使用普通图层并简单地设置cornerRadius,就可以了。

其次是关于内部斑点。请注意,它只是小于整个单位。换句话说,内部斑点的框架必须缩小一定程度。

为此,请在iOS中使用关键的inset(by: UIEdgeInsets调用。经常使用它!

您在iOS中经常使用inset(by: UIEdgeInsets

这是一个重要的小技巧。我真的鼓励您使用inset(by: UIEdgeInsets( ...,在其中模糊地写下“顶部,左侧,底部,右侧”

另一个变体insetBy#dx#dy容易引起混乱;目前尚不清楚您是要加倍数量还是要加倍。

我个人建议使用“长格式” inset(by: UIEdgeInsets( ...,因为毫无疑问
会出现,这是怎么回事。

因此,我们现在完全完成了内点:
override func layoutSubviews() {
super.layoutSubviews()

outerBand.frame = bounds
outerBand.lineWidth = thicknessOfOuterRing

centralBlob.frame =
bounds.inset(by: UIEdgeInsets(top: both, left: both, bottom: both, right: both))
centralBlob.cornerRadius = centralBlob.bounds.width / 2.0
}

enter image description here

最后,这是您问题的核心:

外圈是使用形状层而非普通层制成的。

形状层由路径定义。

这是在iOS中使用形状图层和路径的核心“令人惊讶的技巧”:

4.在iOS中,实际上是在layoutSubviews中创建形状图层的路径。

以我的经验,这使程序员从其他平台迁移到iOS时感到非常困惑,但这就是原因。

因此,让我们创建一个计算变量,为我们创建路径。

请注意,您肯定会使用方便的 inset(by: UIEdgeInsets( ...调用。

不要忘记,在调用此函数时,您 应该已经正确设置了所有涉及的帧。

最后,Apple请给我们一个非常方便的 UIBezierPath#ovalIn调用,这样您就不必傻瓜arcs和Pi!

所以这很容易...
var circlePathForCurrentLayout: UIBezierPath {
var b = bounds
b = b.inset(by: UIEdgeInsets(top: halfT, left: halfT, bottom: halfT, right: halfT))
let p = UIBezierPath(ovalIn: b)
return p
}

然后,如粗体字母所示,在iOS 中,您令人惊讶地在layoutSubviews 中设置了形状图层的实际路径。
override func layoutSubviews() {
super.layoutSubviews()

outerBand.frame = bounds
outerBand.lineWidth = thicknessOfOuterRing
outerBand.path = circlePathForCurrentLayout.cgPath

centralBlob.frame =
bounds.inset(by: UIEdgeInsets(top: both, left: both, bottom: both, right: both))
centralBlob.cornerRadius = centralBlob.bounds.width / 2.0
}

enter image description here

回顾:

1.与往常一样,制作图层,然后在layoutSubviews中设置其框架。

2.制作完图层后,设置它们的所有“固定”方面。

3.在layoutSubviews中设置图层的所有“更改”方面。

4.出人意料的是,在iOS中,您实际上是在layoutSubviews中创建形状图层的路径。

这就是整个过程:
//  Thingy.swift
// Created for SO on 11/3/19.

import UIKit

class Thingy: UIView {

var thicknessOfOuterRing: CGFloat = 20.0 {
didSet{ setNeedsLayout() }
}

var thicknessOfTheGap: CGFloat = 20.0 {
didSet{ setNeedsLayout() }
}

var halfT: CGFloat { return thicknessOfOuterRing / 2.0 }
var both: CGFloat { return thicknessOfOuterRing + thicknessOfTheGap }

var circlePathForCurrentLayout: UIBezierPath {
var b = bounds
b = b.inset(by:
UIEdgeInsets(top: halfT, left: halfT, bottom: halfT, right: halfT))
let p = UIBezierPath(ovalIn: b)
return p
}

private lazy var outerBand: CAShapeLayer = {
let l = CAShapeLayer()
l.fillColor = UIColor.clear.cgColor
l.strokeColor = UIColor.black.cgColor
layer.addSublayer(l)
return l
}()

private lazy var centralBlob: CALayer = {
let l = CALayer()
l.backgroundColor = UIColor.black.cgColor
layer.addSublayer(l)
return l
}()

override func layoutSubviews() {
super.layoutSubviews()

outerBand.frame = bounds
outerBand.lineWidth = thicknessOfOuterRing
outerBand.path = circlePathForCurrentLayout.cgPath

centralBlob.frame = bounds.inset(by:
UIEdgeInsets(top: both, left: both, bottom: both, right: both))
centralBlob.cornerRadius = centralBlob.bounds.width / 2.0
}
}

下一步:

如果您想接受中间有图像的挑战: link

enter image description here

如果愿意,请带阴影: link

看着渐变? link

偏弧: link

关于ios - 使用UIBezierPath绘制同心圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58680306/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com