我有一个自定义视图,我用它来使用 CAShapeLayer 创建形状。这是当前输出。
我想要实现的是:
图中突出显示的白色圆圈
这是我用来创建弧形的代码
let gaugeLayer = CAShapeLayer()
if bgLayer == nil {
bgLayer = CAShapeLayer.getOval(lineWidth, strokeStart: 0, strokeEnd: 0.75, strokeColor: _bgStartColor, fillColor: UIColor.clear, shadowRadius: shadowRadius, shadowOpacity: shadowOpacity, shadowOffsset: CGSize.zero, bounds: bounds)
bgLayer.frame = layer.bounds
gaugeLayer.addSublayer(bgLayer)
}
if ringLayer == nil {
ringLayer = CAShapeLayer.getOval(lineWidth, strokeStart: 0, strokeEnd: 0.75, strokeColor: UIColor.clear, fillColor: UIColor.clear, shadowRadius: shadowRadius, shadowOpacity: shadowOpacity, shadowOffsset: CGSize.zero, bounds: bounds)
ringLayer.frame = layer.bounds
gaugeLayer.addSublayer(ringLayer)
}
//...
ringLayer.lineCap = .round
bgLayer.lineCap = .round
return gaugeLayer
getOval:
func getOval(_ lineWidth: CGFloat,
strokeStart: CGFloat,
strokeEnd: CGFloat,
strokeColor: UIColor,
fillColor: UIColor,
shadowRadius: CGFloat,
shadowOpacity: Float,
shadowOffsset: CGSize,
bounds: CGRect,
rotateAngle: Double? = nil,
anchorPoint: CGPoint? = nil,) -> CAShapeLayer {
var arc = CAShapeLayer()
let rect = bounds.insetBy(dx: CGFloat(lineWidth / 2.0), dy: CGFloat(lineWidth / 2.0))
let arcDiameter: CGFloat = min(bounds.width, bounds.height) - lineWidth
let X = bounds.midX
let Y = bounds.midY
arc.path = UIBezierPath(ovalIn: CGRect(x: (X - (arcDiameter / 2)), y: (Y - (arcDiameter / 2)), width: arcDiameter, height: arcDiameter)).cgPath
////
arc.lineWidth = lineWidth
arc.strokeStart = strokeStart
arc.strokeColor = strokeColor.cgColor
arc.fillColor = fillColor.cgColor
arc.shadowColor = UIColor.black.cgColor
arc.shadowRadius = shadowRadius
arc.shadowOpacity = shadowOpacity
arc.shadowOffset = shadowOffsset
if let anchorPoint = anchorPoint {
arc.anchorPoint = anchorPoint
}
if let rotateAngle = rotateAngle {
arc.transform = CATransform3DRotate(arc.transform, CGFloat(rotateAngle), 0, 0, 1)
}
arc.strokeEnd = strokeEnd
////
return arc
}
白色圆圈不是静止的,它可以沿着弧线移动(因为它是蓝色进度条的尖端)。我知道如何创建圆形,但我不确定如何从这里开始。我怎样才能做到这一点?
编辑:
根据评论,我添加了白点,但位置不正确。我的计算有误吗?
lazy var currentPositionDotLayer: CALayer = {
let layer = CALayer()
layer.backgroundColor = UIColor.white.cgColor
let rect = CGRect(x: 0, y: 0, width: lineWidth, height: lineWidth)
layer.frame = rect
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.white.cgColor, UIColor.clear.cgColor]
gradientLayer.type = .radial
gradientLayer.frame = rect
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1, y: 1)
gradientLayer.locations = [0.5, 1]
layer.mask = gradientLayer
return layer
}()
open override func layoutSubviews() {
...
layer.addSublayer(currentPositionDotLayer)
updatePaths()
...
}
func updatePaths() {
let rect = bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)
let halfWidth = rect.width / 2
let height = rect.height
let theta = atan(halfWidth / height)
let radius = (min(bounds.width, bounds.height) - lineWidth) / 2
let center = CGPoint(x: rect.midX, y: rect.minY + radius)
let delta = (Double.pi / 2 - theta) * 2
let startAngle = Double.pi * 3 / 2 - delta
let endAngle = .pi * 3 / 2 + delta
let currentAngle = (endAngle - startAngle) * (rate / maxValue) + startAngle
let dotCenter = CGPoint(x: center.x + radius * cos(currentAngle),
y: center.y + radius * sin(currentAngle))
currentPositionDotLayer.position = dotCenter
}
CAShapeLayer 用一种颜色绘制整个形状。
您需要为弧形创建两个自定义形状,一端凸出,另一端凹入,或者浅蓝色弧形、深蓝色弧形和白色圆圈。使用 2 个带圆端的法线弧和一个圆会更简单,因为它会使用现有的形状。
如果你把白色圆圈放在其他两个上面并正确放置它们,它会给出你想要的结果。