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

iOS/Swift开发:如何在Bing Map上用手指绘制折线、多边形并获取动态坐标

实现Bing Map拖拽绘制/擦除地理围栏及坐标获取

1. 初始化核心变量

先定义管理绘制状态、坐标集合及图形元素的变量,统一维护绘制逻辑:

import UIKit
import MicrosoftMaps

class MapDrawingVC: UIViewController {
    @IBOutlet weak var mapView: MSMapView!
    
    // 绘制模式枚举
    enum DrawingMode {
        case none, drawPolyline, drawPolygon, erase
    }
    
    var currentMode: DrawingMode = .none
    var currentCoords: [MSGeoposition] = []
    var currentShape: MSMapElement? // 当前绘制的折线/多边形
    let drawingLayer = MSMapElementLayer() // 专属绘制图层
}

2. 初始化地图与绘制图层

在viewDidLoad中完成地图基础配置,添加专属绘制图层:

override func viewDidLoad() {
    super.viewDidLoad()
    // 设置初始地图视角(以北京为例)
    mapView.setScene(MSMapScene(latitude: 39.9042, longitude: 116.4074, zoomLevel: 15), animated: false)
    // 添加绘制图层到地图
    drawingLayer.zIndex = 1
    mapView.layers.add(drawingLayer)
}

3. 处理触摸事件实现拖拽绘制

重写触摸方法,将屏幕坐标转换为地理坐标,动态更新坐标集合与图形:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    
    if currentMode == .erase {
        // 擦除模式下处理点选移除
        let screenPoint = touch.location(in: mapView)
        let nearbyElements = mapView.elements(at: screenPoint)
        for element in nearbyElements {
            if element is MSMapPolyline || element is MSMapPolygon {
                drawingLayer.elements.remove(element)
                if element === currentShape {
                    currentShape = nil
                    currentCoords.removeAll()
                }
                break
            }
        }
        return
    }
    
    // 绘制模式下初始化起点
    guard currentMode != .none else { return }
    let screenPoint = touch.location(in: mapView)
    guard let geopos = mapView.convert(screenPoint, to: .geographic) else { return }
    currentCoords = [geopos]
    updateCurrentShape()
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard currentMode != .none, currentMode != .erase, let touch = touches.first else { return }
    
    let screenPoint = touch.location(in: mapView)
    guard let geopos = mapView.convert(screenPoint, to: .geographic) else { return }
    currentCoords.append(geopos)
    updateCurrentShape()
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard currentMode != .none, currentMode != .erase else { return }
    
    // 校验图形点数:折线至少2个点,多边形至少3个点
    let isValid = (currentMode == .drawPolyline && currentCoords.count >= 2) || 
                  (currentMode == .drawPolygon && currentCoords.count >= 3)
    if !isValid {
        currentShape.flatMap { drawingLayer.elements.remove($0) }
        currentShape = nil
        currentCoords.removeAll()
    }
}

4. 动态更新图形元素

根据当前绘制模式,创建或更新折线/多边形:

private func updateCurrentShape() {
    // 移除旧的临时图形
    currentShape.flatMap { drawingLayer.elements.remove($0) }
    guard currentCoords.count >= 2 else { return }
    
    let geopath = MSGeopath(positions: currentCoords)
    
    switch currentMode {
    case .drawPolyline:
        let polyline = MSMapPolyline(path: geopath)
        polyline.strokeColor = .black
        polyline.strokeWidth = 3
        currentShape = polyline
        drawingLayer.elements.add(polyline)
    case .drawPolygon:
        let polygon = MSMapPolygon(path: geopath)
        polygon.strokeColor = .black
        polygon.strokeWidth = 3
        polygon.fillColor = UIColor.blue.withAlphaComponent(0.2)
        currentShape = polygon
        drawingLayer.elements.add(polygon)
    default: break
    }
}

5. 扩展功能:批量清除与坐标获取

5.1 清除所有绘制图形

func clearAllDrawings() {
    drawingLayer.elements.removeAll()
    currentShape = nil
    currentCoords.removeAll()
}

5.2 获取当前图形的动态坐标

// 获取当前图形的所有坐标
func getCurrentShapeCoordinates() -> [MSGeoposition]? {
    guard currentShape != nil else { return nil }
    return currentCoords
}

// 可选:实时监听坐标变化(通过闭包回调)
var coordinateUpdateHandler: (([MSGeoposition])->Void)?

// 在updateCurrentShape方法末尾添加回调
coordinateUpdateHandler?(currentCoords)

模式切换示例

通过按钮触发绘制/擦除模式切换:

@IBAction func switchToPolyline(_ sender: UIButton) {
    currentMode = .drawPolyline
}

@IBAction func switchToPolygon(_ sender: UIButton) {
    currentMode = .drawPolygon
}

@IBAction func switchToErase(_ sender: UIButton) {
    currentMode = .erase
}

@IBAction func clearAll(_ sender: UIButton) {
    clearAllDrawings()
}

@IBAction func getCoords(_ sender: UIButton) {
    if let coords = getCurrentShapeCoordinates() {
        let coordStrs = coords.map { "(\($0.latitude), \($0.longitude))" }
        print("当前图形坐标:\(coordStrs.joined(separator: ", "))")
    }
}

内容的提问来源于stack exchange,提问作者Dhananjay Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 16:03:16