我需要为地图上的每个点分配一个不同的图标。 根据{{3}}
的示例我希望每个文件都从该文件中分配适当的图标。 该文件包含有关每个点的图标的信息。
有关图标的数据可以在“ imageName”属性中找到。 有可能吗?
https://www.mapbox.com/ios-sdk/maps/examples/clustering/
{
"type": "Feature",
"properties": {
"description": "18736 W Peterson Rd, Libertyville",
"name": "Lake County Animal Care and Control",
"hours": "M-F 9am-4:30pm, Sat 9am-12:30pm",
"phone": "847-377-4700",
"imageName": "http://test.com/icon.png"
},
"geometry": {
"coordinates": [
-87.998316,
42.306035
],
"type": "Point"
},
"id": "address.10164434706493830"
}
示例代码:
import Mapbox
class ViewController: UIViewController, MGLMapViewDelegate {
var mapView: MGLMapView!
var icon: UIImage!
var popup: UILabel?
enum CustomError: Error {
case castingError(String)
}
override func viewDidLoad() {
super.viewDidLoad()
mapView = MGLMapView(frame: view.bounds, styleURL: MGLStyle.lightStyleURL)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.tintColor = .darkGray
mapView.delegate = self
view.addSubview(mapView)
let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleMapTap(sender:)))
for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer {
singleTap.require(toFail: recognizer)
}
mapView.addGestureRecognizer(singleTap)
icon = UIImage(named: "port")
}
func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {
let url = URL(fileURLWithPath: Bundle.main.path(forResource: "ports", ofType: "geojson")!)
let source = MGLShapeSource(identifier: "clusteredPorts",
url: url,
options: [.clustered: true, .clusterRadius: icon.size.width])
style.addSource(source)
style.setImage(icon.withRenderingMode(.alwaysTemplate), forName: "icon")
let ports = MGLSymbolStyleLayer(identifier: "ports", source: source)
ports.iconImageName = NSExpression(forConstantValue: "icon")
ports.iconColor = NSExpression(forConstantValue: UIColor.darkGray.withAlphaComponent(0.9))
ports.predicate = NSPredicate(format: "cluster != YES")
style.addLayer(ports)
let stops = [
20: UIColor.lightGray,
50: UIColor.orange,
100: UIColor.red,
200: UIColor.purple
]
let circlesLayer = MGLCircleStyleLayer(identifier: "clusteredPorts", source: source)
circlesLayer.circleRadius = NSExpression(forConstantValue: NSNumber(value: Double(icon.size.width) / 2))
circlesLayer.circleOpacity = NSExpression(forConstantValue: 0.75)
circlesLayer.circleStrokeColor = NSExpression(forConstantValue: UIColor.white.withAlphaComponent(0.75))
circlesLayer.circleStrokeWidth = NSExpression(forConstantValue: 2)
circlesLayer.circleColor = NSExpression(format: "mgl_step:from:stops:(point_count, %@, %@)", UIColor.lightGray, stops)
circlesLayer.predicate = NSPredicate(format: "cluster == YES")
style.addLayer(circlesLayer)
let numbersLayer = MGLSymbolStyleLayer(identifier: "clusteredPortsNumbers", source: source)
numbersLayer.textColor = NSExpression(forConstantValue: UIColor.white)
numbersLayer.textFontSize = NSExpression(forConstantValue: NSNumber(value: Double(icon.size.width) / 2))
numbersLayer.iconAllowsOverlap = NSExpression(forConstantValue: true)
numbersLayer.text = NSExpression(format: "CAST(point_count, 'NSString')")
numbersLayer.predicate = NSPredicate(format: "cluster == YES")
style.addLayer(numbersLayer)
}
func mapViewRegionIsChanging(_ mapView: MGLMapView) {
showPopup(false, animated: false)
}
@objc @IBAction func handleMapTap(sender: UITapGestureRecognizer) throws {
if sender.state == .ended {
let point = sender.location(in: sender.view)
let width = icon.size.width
let rect = CGRect(x: point.x - width / 2, y: point.y - width / 2, width: width, height: width)
let clusters = mapView.visibleFeatures(in: rect, styleLayerIdentifiers: ["clusteredPorts"])
let ports = mapView.visibleFeatures(in: rect, styleLayerIdentifiers: ["ports"])
if !clusters.isEmpty {
showPopup(false, animated: true)
let cluster = clusters.first!
mapView.setCenter(cluster.coordinate, zoomLevel: (mapView.zoomLevel + 1), animated: true)
} else if !ports.isEmpty {
let port = ports.first!
if popup == nil {
popup = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 40))
popup!.backgroundColor = UIColor.white.withAlphaComponent(0.9)
popup!.layer.cornerRadius = 4
popup!.layer.masksToBounds = true
popup!.textAlignment = .center
popup!.lineBreakMode = .byTruncatingTail
popup!.font = UIFont.systemFont(ofSize: 16)
popup!.textColor = UIColor.black
popup!.alpha = 0
view.addSubview(popup!)
}
guard let portName = port.attribute(forKey: "name")! as? String else {
throw CustomError.castingError("Could not cast port name to string")
}
popup!.text = portName
let size = (popup!.text! as NSString).size(withAttributes: [NSAttributedStringKey.font: popup!.font])
popup!.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height).insetBy(dx: -10, dy: -10)
let point = mapView.convert(port.coordinate, toPointTo: mapView)
popup!.center = CGPoint(x: point.x, y: point.y - 50)
if popup!.alpha < 1 {
showPopup(true, animated: true)
}
} else {
showPopup(false, animated: true)
}
}
}
func showPopup(_ shouldShow: Bool, animated: Bool) {
let alpha: CGFloat = (shouldShow ? 1 : 0)
if animated {
UIView.animate(withDuration: 0.25) { [unowned self] in
self.popup?.alpha = alpha
}
} else {
popup?.alpha = alpha
}
}
}