Внутренняя тень для частичной дуги с помощью Swift

#swift #calayer #shadow #shadowpath

#swift #calayer #тень #shadowpath

Вопрос:

Я хочу создать внутреннюю тень для дуги, но вместо тени я получаю половину круга (см. Изображение ниже).

Мой код:

 let rect = self.bounds
let segmentArcPath = UIBezierPath()
segmentArcPath.addArc(withCenter: rect.center,
                      radius: (rect.height - insetShadow) / 2,
                      startAngle: -.pi/2,
                      endAngle: value * 2 * .pi - .pi/2,
                      clockwise: true)

shadowPath = segmentArcPath.cgPath
  

Текущий результат из приведенного выше кода и ожидаемый результат

Я пытался добавить два пути (чтобы не закрывать тень), но безуспешно:

 let rect = self.bounds
let segmentArcPath = UIBezierPath()
segmentArcPath.addArc(withCenter: rect.center,
                      radius: (rect.height - insetShadow) / 2,
                      startAngle: internalStrokeStart,
                      endAngle: internalStrokeEnd,
                      clockwise: true)

let segmentArcPath2 = UIBezierPath()
segmentArcPath2.addArc(withCenter: rect.center,
                      radius: (rect.height - insetShadow) / 2 - 5,
                      startAngle: internalStrokeStart,
                      endAngle: internalStrokeEnd,
                      clockwise: false)

segmentArcPath.append(segmentArcPath2)
shadowPath = segmentArcPath.cgPath
  

Как я могу создать тень, как показано на изображении выше? У вас есть какие-нибудь подсказки?

Комментарии:

1. Создайте только один UIBezierPath . После рисования внешней дуги нарисуйте линию длиной 5 единиц по направлению к центру дуги, затем вызовите addArc , чтобы добавить внутреннюю дугу к тому же контуру.

Ответ №1:

Как рекомендовано @vacawama:

Создайте только один UIBezierPath. После рисования внешней дуги нарисуйте линию длиной 5 единиц по направлению к центру дуги, затем вызовите AddArc, чтобы добавить внутреннюю дугу к тому же контуру

 let rect = self.bounds
let outerRadius = (rect.height - insetShadow) / 2
let segmentArcPath = UIBezierPath()
segmentArcPath.addArc(withCenter: rect.center,
                      radius: outerRadius,
                      startAngle: internalStrokeStart,
                      endAngle: internalStrokeEnd,
                      clockwise: true)
let innerCircleRadius = outerRadius - 2
let startPointXInnerCircle = cos(internalStrokeEnd) * innerCircleRadius   rect.center.x
let startPointYInnerCircle = sin(internalStrokeEnd) * innerCircleRadius   rect.center.y

segmentArcPath.addLine(to: CGPoint(x: startPointXInnerCircle, y: startPointYInnerCircle))

segmentArcPath.addArc(withCenter: rect.center,
                      radius: innerCircleRadius,
                      startAngle: internalStrokeEnd,
                      endAngle: internalStrokeStart,
                      clockwise: false)

shadowPath = segmentArcPath.cgPath
  

Комментарии:

1. Зачем добавлять строку скорее с помощью addLine(to:) , а не move(to:) вместо? Разве это не добавило бы артефакт в чертеж?

2. @DuncanC: Для тени вам нужен замкнутый путь. Когда путь не закрыт (например, с помощью перемещения), он автоматически закрывается кратчайшим возможным путем и, как следствие, приводит к артефактам.