import SwiftUI import SVGKit struct SVGImage: UIViewRepresentable { let svgName: String var contentMode: ContentMode = .fit var tintColor: Color? private var svgPath: String { return svgName } private func createImageView() -> SVGKFastImageView { let emptySVGString = """ """ if let data = emptySVGString.data(using: .utf8), let svgImage = SVGKImage(data: data) { let imageView = SVGKFastImageView(svgkImage: svgImage) ?? SVGKFastImageView() imageView.contentMode = .scaleAspectFit imageView.backgroundColor = .clear return imageView } let fallbackView = SVGKFastImageView() fallbackView.backgroundColor = .clear return fallbackView } func makeUIView(context: Context) -> SVGKFastImageView { print("🔄 开始加载SVG: \(svgName)") let imageView = createImageView() loadSVG(into: imageView) configureView(imageView) return imageView } private func loadSVG(into imageView: SVGKFastImageView) { guard let path = Bundle.main.path(forResource: svgPath, ofType: "svg") else { print("⚠️ 在main bundle中找不到文件: \(svgPath).svg") return } let url = URL(fileURLWithPath: path) guard let svgImage = SVGKImage(contentsOf: url) else { print("❌ 无法从URL创建SVG: \(path)") return } // 设置SVG的尺寸为容器大小 let containerSize = imageView.bounds.size if containerSize != .zero { svgImage.size = containerSize } else { // 如果容器大小未知,设置一个默认大小 svgImage.size = CGSize(width: 100, height: 100) } print("✅ 成功加载SVG: \(svgName), 尺寸: \(svgImage.size)") DispatchQueue.main.async { imageView.image = svgImage imageView.setNeedsLayout() imageView.layoutIfNeeded() } } private func configureView(_ imageView: SVGKFastImageView) { imageView.contentMode = contentMode == .fit ? .scaleAspectFit : .scaleAspectFill imageView.clipsToBounds = true imageView.translatesAutoresizingMaskIntoConstraints = false imageView.backgroundColor = .clear // 确保图片视图可以正确缩放 imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight] if let tintColor = tintColor?.uiColor { imageView.tintColor = tintColor DispatchQueue.main.async { self.applyTintColor(tintColor, to: imageView.layer) } } } private func applyTintColor(_ color: UIColor, to layer: CALayer) { if let shapeLayer = layer as? CAShapeLayer { shapeLayer.fillColor = color.cgColor } layer.sublayers?.forEach { sublayer in applyTintColor(color, to: sublayer) } } func updateUIView(_ uiView: SVGKFastImageView, context: Context) { loadSVG(into: uiView) if let tintColor = tintColor?.uiColor { uiView.tintColor = tintColor DispatchQueue.main.async { self.applyTintColor(tintColor, to: uiView.layer) } } uiView.contentMode = contentMode == .fit ? .scaleAspectFit : .scaleAspectFill } func sizeThatFits(_ proposal: ProposedViewSize, uiView: SVGKFastImageView, context: Context) -> CGSize? { return nil } } // MARK: - ContentMode extension SVGImage { enum ContentMode { case fit // 保持宽高比,适应容器 case fill // 保持宽高比,填充容器(可能被裁剪) } } // MARK: - Preview #Preview { VStack(spacing: 20) { Text("IP SVG") SVGImage(svgName: "IP") .frame(width: 100, height: 100) .background(Color.gray.opacity(0.2)) .border(Color.red, width: 1) Text("Pioneer SVG") SVGImage(svgName: "Pioneer", contentMode: .fill) .frame(width: 100, height: 50) .background(Color.gray.opacity(0.2)) .border(Color.blue, width: 1) .clipped() } .padding() } // MARK: - Color Extension private extension Color { var uiColor: UIColor { return UIColor(self) } }