You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS(UIKit)中如何按百分比显示并填充SVG国家/区域地图

解决方案:iOS 分级统计图(Choropleth Map)实现

一、基于 SVG 的精准填充方案(解决你遇到的颜色修改问题)

1. SVGKit 实操步骤

核心思路是通过 SVG 中区域的唯一 id 匹配数据,遍历图层修改对应 CAShapeLayer 的填充色:

  • 先确保你的 SVG 文件中,每个需要填充的区域都带有唯一 id(比如 <path id="london" d="..."/>)
  • 加载并修改颜色的代码示例:
import SVGKit

// 加载 SVG 文件
let svgURL = Bundle.main.url(forResource: "uk-map", withExtension: "svg")!
let svgImage = SVGKImage(contentsOf: svgURL)
let svgView = SVGKFastImageView(image: svgImage)
svgView.frame = CGRect(x: 20, y: 20, width: view.bounds.width-40, height: view.bounds.height-40)
view.addSubview(svgView)

// 模拟数据:区域 id -> 百分比
let regionData = ["london": 85, "manchester": 60, "birmingham": 45]

// 百分比转颜色的映射函数
func getColor(for percentage: Int) -> UIColor {
    switch percentage {
    case 0..<30: return UIColor(red: 0.8, green: 0.8, blue: 0.8, alpha: 1)
    case 30..<60: return UIColor(red: 1, green: 0.6, blue: 0, alpha: 1)
    case 60...100: return UIColor(red: 0.8, green: 0, blue: 0, alpha: 1)
    default: return .gray
    }
}

// 递归遍历图层,修改对应区域颜色
func updateLayerColors(layer: CALayer) {
    if let shapeLayer = layer as? CAShapeLayer, let regionId = shapeLayer.name {
        if let pct = regionData[regionId] {
            shapeLayer.fillColor = getColor(for: pct).cgColor
            shapeLayer.strokeColor = UIColor.black.cgColor
            shapeLayer.lineWidth = 0.5
        }
    }
    layer.sublayers?.forEach(updateLayerColors)
}

// 执行颜色更新
updateLayerColors(layer: svgView.layer)

注意:SVGKit 会自动将 SVG 元素的 id 赋值给 CAShapeLayer 的 name 属性,这是匹配的关键。

2. SwiftSVG 进阶用法

如果用 SwiftSVG,可直接解析生成图层后遍历修改:

import SwiftSVG

let svgView = UIView(frame: CGRect(x: 20, y: 20, width: view.bounds.width-40, height: view.bounds.height-40))
view.addSubview(svgView)

SVGParser.parse(url: Bundle.main.url(forResource: "uk-map", withExtension: "svg")!) { layer in
    layer.frame = svgView.bounds
    svgView.layer.addSublayer(layer)
    
    // 复用上面的 regionData、getColor、updateLayerColors 函数
    updateLayerColors(layer: layer)
}

二、不使用 SVG 的替代方案

1. MapKit 自定义多边形绘制

适合国家/大洲级的粗粒度地图,通过经纬度坐标生成 MKPolygon 并设置样式:

import MapKit

class MapVC: UIViewController, MKMapViewDelegate {
    @IBOutlet weak var mapView: MKMapView!
    let regionData = ["london": 85]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.delegate = self
        
        // 示例:伦敦区域的经纬度轮廓(实际需导入完整坐标数据)
        let londonCoords = [
            CLLocationCoordinate2D(latitude: 51.5074, longitude: -0.1278),
            // 更多坐标点...
        ]
        let londonPolygon = MKPolygon(coordinates: londonCoords, count: londonCoords.count)
        londonPolygon.title = "london"
        mapView.addOverlay(londonPolygon)
    }
    
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        guard let polygon = overlay as? MKPolygon else { return MKOverlayRenderer() }
        let renderer = MKPolygonRenderer(polygon: polygon)
        if let regionName = polygon.title, let pct = regionData[regionName] {
            renderer.fillColor = getColor(for: pct).withAlphaComponent(0.7)
            renderer.strokeColor = .black
            renderer.lineWidth = 1
        }
        return renderer
    }
}

2. 专业地图可视化库推荐

  • Mapbox iOS SDK:支持加载自定义矢量瓦片(可将 SVG 转换为矢量瓦片),能动态配置区域样式,适合专业级需求。
  • Charts:虽主打图表,但可结合自定义 UIBezierPath 实现轻量化的分级地图。

三、核心注意事项

  • 确保区域标识(SVG 的 id 或 MapKit 多边形的 title)与数据字典的 Key 完全匹配,这是动态填充的基础。
  • 颜色映射尽量采用渐变或区分度高的色系,提升可读性。
  • 若区域数量较多,建议提前缓存图层引用,避免频繁遍历影响性能。

内容的提问来源于stack exchange,提问作者Guillaume B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:59:58