如何缩放和居中 UIBezierPath?
How to Scale and Center UIBezierPath?
我正在使用 BezierPath,可以成功地在视图中制作基本的星形,效果很好。但是,视图的大小可以更改。当视图大小改变时,我无法将这条贝塞尔路径居中,我设法缩放它,但居中对我来说很难。
private func pointFrom(_ angle: CGFloat, radius: CGFloat, offset: CGPoint) -> CGPoint {
return CGPoint(x: radius * cos(angle) + offset.x, y: radius * sin(angle) + offset.y)//CGPointMake(radius * cos(angle) + offset.x, radius * sin(angle) + offset.y)
}
private func generateStar(width:CGFloat, height:CGFloat, radius:CGFloat) -> CAShapeLayer{
let path = UIBezierPath()
var scale = width / height
if width > height{
scale = height / width
}
let starExtrusion:CGFloat = 60.0
let center = CGPoint(x: width / 2.0, y: height / 2.0)
let pointsOnStar = 5
var angle:CGFloat = -CGFloat(.pi / 2.0)
let angleIncrement = CGFloat(.pi * 2.0 / Double(pointsOnStar))
let radius = width / 2.0
var firstPoint = true
for _ in 1...pointsOnStar {
let point = pointFrom(angle, radius: radius, offset: center)
let nextPoint = pointFrom(angle + angleIncrement, radius: radius, offset: center)
let midPoint = pointFrom(angle + angleIncrement / 2.0, radius: starExtrusion, offset: center)
if firstPoint {
firstPoint = false
path.move(to: point)
}
path.addLine(to: midPoint)//addLineToPoint(midPoint)
path.addLine(to: nextPoint)//addLineToPoint(nextPoint)
angle += angleIncrement
}
path.apply(CGAffineTransform(scaleX: scale, y: scale))
path.close()
let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
return maskLayer
}
我怎样才能做到这一点?谢谢!
UIView 的 layoutSubviews
在调整大小时被调用,您可以通过覆盖该方法来重置遮罩。
您的路径中心使用此命令移动:
path.apply(CGAffineTransform(scaleX: scale, y: scale))
为了让你的 center
保持在中心,将它缩放 1 / scale
这样当它被缩放 scale
时,它最终会在视图的中心(因为(1 / scale) * scale == 1
):
变化:
let center = CGPoint(x: width / 2.0, y: height / 2.0)
至:
let center = CGPoint(x: width / 2.0 / scale, y: height / 2.0 / scale)
这两个缩放比例相互抵消,然后路径的中心在最初计算的位置结束。
就是说,height != width
时您正在缩小星标。如果您忘记缩放并仅选择 width
和 height
中的最小值作为 radius
计算,您可能会得到更好的结果:
去掉scale
,或者设置为1.0
,然后
变化:
let radius = width / 2.0
至:
let radius = min(width, height) / 2.0
这将使星星尽可能大,同时仍完全适合视图。
如您所见,随着恒星变小,它会变得 "fat"(更圆)。这是因为对于 starExtrusion
,您有一个硬编码常量 60.0
。该值应基于 radius
.
计算后设置starExtrusion
radius
:
let radius = min(width, height) / 2.0
let starExtrusion = radius * 0.4
您可以改变 0.4
乘数来改变星星的形状。
我正在使用 BezierPath,可以成功地在视图中制作基本的星形,效果很好。但是,视图的大小可以更改。当视图大小改变时,我无法将这条贝塞尔路径居中,我设法缩放它,但居中对我来说很难。
private func pointFrom(_ angle: CGFloat, radius: CGFloat, offset: CGPoint) -> CGPoint {
return CGPoint(x: radius * cos(angle) + offset.x, y: radius * sin(angle) + offset.y)//CGPointMake(radius * cos(angle) + offset.x, radius * sin(angle) + offset.y)
}
private func generateStar(width:CGFloat, height:CGFloat, radius:CGFloat) -> CAShapeLayer{
let path = UIBezierPath()
var scale = width / height
if width > height{
scale = height / width
}
let starExtrusion:CGFloat = 60.0
let center = CGPoint(x: width / 2.0, y: height / 2.0)
let pointsOnStar = 5
var angle:CGFloat = -CGFloat(.pi / 2.0)
let angleIncrement = CGFloat(.pi * 2.0 / Double(pointsOnStar))
let radius = width / 2.0
var firstPoint = true
for _ in 1...pointsOnStar {
let point = pointFrom(angle, radius: radius, offset: center)
let nextPoint = pointFrom(angle + angleIncrement, radius: radius, offset: center)
let midPoint = pointFrom(angle + angleIncrement / 2.0, radius: starExtrusion, offset: center)
if firstPoint {
firstPoint = false
path.move(to: point)
}
path.addLine(to: midPoint)//addLineToPoint(midPoint)
path.addLine(to: nextPoint)//addLineToPoint(nextPoint)
angle += angleIncrement
}
path.apply(CGAffineTransform(scaleX: scale, y: scale))
path.close()
let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
return maskLayer
}
我怎样才能做到这一点?谢谢!
UIView 的 layoutSubviews
在调整大小时被调用,您可以通过覆盖该方法来重置遮罩。
您的路径中心使用此命令移动:
path.apply(CGAffineTransform(scaleX: scale, y: scale))
为了让你的 center
保持在中心,将它缩放 1 / scale
这样当它被缩放 scale
时,它最终会在视图的中心(因为(1 / scale) * scale == 1
):
变化:
let center = CGPoint(x: width / 2.0, y: height / 2.0)
至:
let center = CGPoint(x: width / 2.0 / scale, y: height / 2.0 / scale)
这两个缩放比例相互抵消,然后路径的中心在最初计算的位置结束。
就是说,height != width
时您正在缩小星标。如果您忘记缩放并仅选择 width
和 height
中的最小值作为 radius
计算,您可能会得到更好的结果:
去掉scale
,或者设置为1.0
,然后
变化:
let radius = width / 2.0
至:
let radius = min(width, height) / 2.0
这将使星星尽可能大,同时仍完全适合视图。
如您所见,随着恒星变小,它会变得 "fat"(更圆)。这是因为对于 starExtrusion
,您有一个硬编码常量 60.0
。该值应基于 radius
.
计算后设置starExtrusion
radius
:
let radius = min(width, height) / 2.0
let starExtrusion = radius * 0.4
您可以改变 0.4
乘数来改变星星的形状。