Mapbox群集点自定义图标-Swift

时间:2018-10-28 12:25:46

标签: ios swift xcode mapbox mapbox-marker

我需要为地图上的每个点分配一个不同的图标。 根据{{​​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
        }
    }

}

0 个答案:

没有答案