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
相关产品推荐
相关产品推荐

