tgoop.com/mobileproglib/6332
Create:
Last Update:
Last Update:
Новый язык дизайна Apple представил эффект светящейся анимированной обводки, которая изящно и динамично подсвечивает формы и компоненты. Давайте рассмотрим, как воссоздать этот эффект в SwiftUI с помощью многоразовых расширений.
🔹 Расширения для View
extension View {
@MainActor
func intelligenceBackground<S: InsettableShape>(in shape: S) -> some View {
background(shape.intelligenceStroke())
}
@MainActor
func intelligenceOverlay<S: InsettableShape>(in shape: S) -> some View {
overlay(shape.intelligenceStroke())
}
}
🔹 Базовая реализация для фигур
extension InsettableShape {
@MainActor
func intelligenceStroke(
lineWidths: [CGFloat] = [6, 9, 11, 15],
blurs: [CGFloat] = [0, 4, 12, 15],
updateInterval: TimeInterval = 0.4
) -> some View {
IntelligenceStrokeView(
shape: self,
lineWidths: lineWidths,
blurs: blurs,
updateInterval: updateInterval
)
.allowsHitTesting(false)
}
}
🔹 Рендеринг слоёв свечения
private struct IntelligenceStrokeView<S: InsettableShape>: View {
let shape: S
let lineWidths: [CGFloat]
let blurs: [CGFloat]
let updateInterval: TimeInterval
@Environment(\.accessibilityReduceMotion) private var reduceMotion
@State private var stops: [Gradient.Stop] = .intelligenceStyle
var body: some View {
let layerCount = min(lineWidths.count, blurs.count)
let gradient = AngularGradient(stops: stops, center: .center)
ZStack {
ForEach(0..<layerCount, id: \.self) { i in
shape
.strokeBorder(gradient, lineWidth: lineWidths[i])
.blur(radius: blurs[i])
.animation(
reduceMotion ? nil : .easeInOut(duration: 0.5 + Double(i) * 0.2),
value: stops
)
}
}
.task {
while !Task.isCancelled {
stops = .intelligenceStyle
try? await Task.sleep(for: .seconds(updateInterval))
}
}
}
}
🔹 Цветовая палитра
private extension Array where Element == Gradient.Stop {
static var intelligenceStyle: [Gradient.Stop] {
let colors = [
Color(red: 188/255, green: 130/255, blue: 243/255),
Color(red: 245/255, green: 185/255, blue: 234/255),
Color(red: 141/255, green: 159/255, blue: 255/255),
Color(red: 255/255, green: 103/255, blue: 120/255),
Color(red: 255/255, green: 186/255, blue: 113/255)
]
return colors
.map { Gradient.Stop(color: $0, location: Double.random(in: 0...1)) }
.sorted { $0.location < $1.location }
}
}
🔹 Использование
// Фон
Text("Текст")
.padding(22)
.intelligenceBackground(in: .capsule)
// Наложение
Text("Текст")
.padding(22)
.intelligenceOverlay(in: .rect(cornerRadius: 22))
🔹 Заключение
Эта реализация показывает, как объединить несколько обводок, размытий и анимированных градиентов для достижения эффекта свечения, аналогичного интерфейсу Apple Intelligence. Результат работает с любым объектом
InsettableShape
. Его можно использовать для современной и выразительной подсветки кнопок, карточек или текстовых контейнеров.#PixelPerfect #MiddlePath #SwiftUI