SwiftUI中绘制带角度线条与圆弧:实现可动画鸟喙
SwiftUI实现贴合鸟身圆周的可动画鸟喙
问题说明
需求是用SwiftUI绘制鸟类图形,以Circle作为鸟身,实现贴合鸟身圆周的上喙(参考红色高亮样式),并支持动画模拟鸟喙开合。
解决方案代码
可动画的鸟喙Shape
struct Beak: Shape { // 控制鸟喙开合角度,0为闭合,数值越大张开幅度越大 var openAngle: Double = 0 // 让角度参数支持SwiftUI动画 var animatableData: Double { get { openAngle } set { openAngle = newValue } } func path(in rect: CGRect) -> Path { var path = Path() // 对齐鸟身的圆心和半径 let bodyCenter = CGPoint(x: rect.width, y: rect.height / 2) let bodyRadius = rect.width / 2 // 计算鸟身与鸟喙连接的两个端点 let startAngle = Angle(degrees: 180 + openAngle) let startPoint = CGPoint( x: bodyCenter.x + bodyRadius * cos(startAngle.radians), y: bodyCenter.y + bodyRadius * sin(startAngle.radians) ) let endAngle = Angle(degrees: 180 - openAngle) let endPoint = CGPoint( x: bodyCenter.x + bodyRadius * cos(endAngle.radians), y: bodyCenter.y + bodyRadius * sin(endAngle.radians) ) // 绘制鸟喙路径:连接点 → 尖端 → 连接点 → 沿鸟身圆弧闭合 path.move(to: startPoint) path.addLine(to: CGPoint(x: 0, y: rect.height / 2)) path.addLine(to: endPoint) path.addArc( center: bodyCenter, radius: bodyRadius, startAngle: endAngle, endAngle: startAngle, clockwise: true ) return path } }
鸟类视图及动画实现
struct BirdView: View { @State private var isBeakOpen = false var body: some View { ZStack { // 鸟身 Circle() .stroke(lineWidth: 10) .frame(width: 150) .overlay { Circle().fill(.yellow) } // 鸟喙:尺寸与鸟身对齐,添加开合动画 Beak(openAngle: isBeakOpen ? 15 : 0) .fill(.black) .frame(width: 75, height: 150) // 宽度为鸟身半径,高度匹配鸟身 .offset(x: -75) // 偏移对齐鸟身圆心 } .frame(width: 300, height: 300) .background(.orange) .onTapGesture { // 点击触发开合动画 withAnimation(.easeInOut(duration: 0.3)) { isBeakOpen.toggle() } } } }
关键说明
- 动画支持:通过
animatableData将openAngle设为可动画参数,实现开合的平滑过渡 - 贴合鸟身:统一鸟喙和鸟身的圆心、半径,用三角函数计算连接点,确保鸟喙边缘完美贴合鸟身圆周
- 灵活调整:修改
openAngle的最大值(示例中为15度)可调整鸟喙张开幅度,点击手势可替换为其他触发逻辑
内容的提问来源于stack exchange,提问作者batman
相关产品推荐
相关产品推荐

