import SwiftUI // MARK: - MiniPlayer 三色图标(播放键 + 三色圆环) struct MiniPlayerIcon: View { var body: some View { GeometryReader { geo in let size = min(geo.size.width, geo.size.height) ZStack { // 三色圆环 RingArc(startAngle: -30, endAngle: 90) .stroke(Color(red: 1.0, green: 0.23, blue: 0.19), lineWidth: size * 0.07) .frame(width: size * 0.82, height: size * 0.82) RingArc(startAngle: 90, endAngle: 210) .stroke(Color(red: 0.20, green: 0.78, blue: 0.35), lineWidth: size * 0.07) .frame(width: size * 0.82, height: size * 0.82) RingArc(startAngle: 210, endAngle: 330) .stroke(Color(red: 0.0, green: 0.48, blue: 1.0), lineWidth: size * 0.07) .frame(width: size * 0.82, height: size * 0.82) // 三色播放三角 TriColorPlay(size: size * 0.38) .offset(x: size * 0.03) // 视觉居中偏移 } .frame(width: size, height: size) } } } // MARK: - 圆弧段 struct RingArc: Shape { let startAngle: Double let endAngle: Double func path(in rect: CGRect) -> Path { var p = Path() let center = CGPoint(x: rect.midX, y: rect.midY) let radius = min(rect.width, rect.height) / 2 p.addArc( center: center, radius: radius, startAngle: .degrees(startAngle), endAngle: .degrees(endAngle), clockwise: false ) return p } } // MARK: - 三色播放三角(中心到三顶点分割) struct TriColorPlay: View { let size: CGFloat var body: some View { Canvas { ctx, canvasSize in let w = canvasSize.width let h = canvasSize.height // 三角顶点(播放键朝右) let top = CGPoint(x: w * 0.15, y: 0) let bottom = CGPoint(x: w * 0.15, y: h) let right = CGPoint(x: w, y: h * 0.5) // 重心 let cx = (top.x + bottom.x + right.x) / 3 let cy = (top.y + bottom.y + right.y) / 3 let center = CGPoint(x: cx, y: cy) // 三色分区 let red = Path { p in p.move(to: center) p.addLine(to: top) p.addLine(to: right) p.closeSubpath() } let green = Path { p in p.move(to: center) p.addLine(to: right) p.addLine(to: bottom) p.closeSubpath() } let blue = Path { p in p.move(to: center) p.addLine(to: bottom) p.addLine(to: top) p.closeSubpath() } ctx.fill(red, with: .color(Color(red: 1.0, green: 0.23, blue: 0.19))) ctx.fill(green, with: .color(Color(red: 0.20, green: 0.78, blue: 0.35))) ctx.fill(blue, with: .color(Color(red: 0.0, green: 0.48, blue: 1.0))) // 分割线 let lineW = max(0.5, w * 0.015) for vertex in [top, bottom, right] { var lp = Path() lp.move(to: center) lp.addLine(to: vertex) ctx.stroke(lp, with: .color(.white.opacity(0.6)), lineWidth: lineW) } } .frame(width: size, height: size) } }