MKMultiPolylineRenderer 有属性吗?

问题描述 投票:0回答:1

有没有办法通过

MKMultiPolylineRenderer
使用每条折线的属性?

或者我是否必须创建不同的渲染器,即使唯一的区别是线宽?

我尝试对

MKMultiPolylineRenderer
进行子分类,但无论如何我都看不到将属性与正在绘制的
CGPath
联系起来。

在下面的代码中,

draw(mapRect:zoomScale:in:)
显示我有1197条折线,但是
strokePath(in:)
每次绘制调用仅调用一次。

如果我能以某种方式知道它正在抚摸哪个路径号,我可以将属性绑定到中风路径函数。由于 draw(mapRect:) 只绘制一条路径,所以我不知道该怎么做。如果中风路径只提供一个索引我就准备好了。

我想我可以完全重写绘制函数(而不是调用它的超级函数),但我会渲染所有 1197 条路径 1197 次,因为我不知道每次调用渲染的是什么路径。

class MyMultiPolylineRenderer: MKMultiPolylineRenderer {
    
    //Even though there are 1197 polylines, this is called once per draw(mapRect:)
    override func strokePath(_ path: CGPath, in context: CGContext) {
        super.strokePath(path, in: context)
        print("strokePath")
    }
    
    override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
        
        //Causes a single call to strokePath
        super.draw(mapRect, zoomScale: zoomScale, in: context)

        var counter = 0
        for poly in self.multiPolyline.polylines {
            counter += 1
        }
        
        //polylines counter: 1197
        print("polylines counter: \(counter)")
    }
}
ios mapkit mkpolyline mkmultipolylinerenderer
1个回答
0
投票

首先我们需要一条对其颜色有意见的折线

class ColoredPolyline: MKPolyline {
    var strokeColor: UIColor?
}

让我们创建一些测试数据: 从圣家堂到蓝色博物馆的蓝色直线 还有一条从圣家堂到玛丽蒂姆博物馆的黄色直线:

func createTestColoredMultiPolyline() -> MKMultiPolyline {
    let sagradaFamília = CLLocationCoordinate2D(latitude: 41.4035944, longitude: 2.1743616)
    let museuBlau = CLLocationCoordinate2D(latitude: 41.41103109073135, longitude: 2.221040725708008)
    let museuMaritim = CLLocationCoordinate2D(latitude: 41.37546408659406, longitude: 2.1759045124053955)
    
    let toBlauCoordinates = [sagradaFamília, museuBlau]
    let polylineToMuseuBlau = ColoredPolyline(coordinates: toBlauCoordinates, count: toBlauCoordinates.count)
    polylineToMuseuBlau.strokeColor = UIColor.blue
    
    let toMaritimCoordinates = [sagradaFamília, museuMaritim]
    let polylineToMuseuMaritim = ColoredPolyline(coordinates: toMaritimCoordinates, count: toMaritimCoordinates.count)
    polylineToMuseuMaritim.strokeColor = UIColor.yellow
    
    let testMultiPolyline = MKMultiPolyline([polylineToMuseuBlau, polylineToMuseuMaritim])
    
    return testMultiPolyline
}

请注意,如果您将这些多段线绘制在彼此之上,这些多段线的顺序很重要。

现在让我们编写一个尊重

MKMultiPolylineRenderer
颜色的
ColoredPolyline
(并在其他情况下使用
MKMultiPolylineRenderer
的颜色):

class MultiColorMultipolylinerenderer: MKMultiPolylineRenderer {
    
    override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
        let roadWidth = MKRoadWidthAtZoomScale(zoomScale)
        
        /// if oloylines draw on top of each other the creator of self.multiPolyline is responsible for the correct sequence
        let polylines = self.multiPolyline.polylines
        
        context.saveGState()

        for polyline in polylines {
            // ger coordinates of polyline
            let polylineMapPoints = polyline.coordinates.map { coord in
                MKMapPoint(coord)
            }
            guard polylineMapPoints.count > 0 else {
                continue
            }

            let coloredPolyline = polyline as? ColoredPolyline
            // usually all polylines in a MultiColorMultipolylinerenderer are rendered with the same self.strokeColor
            // but we let ColoredPolyline have its own opinion
            let polylineStrokeColor = coloredPolyline?.strokeColor ?? self.strokeColor ?? UIColor.label
            

            // stroke properties to context
            context.setBlendMode(CGBlendMode.exclusion)
            context.setStrokeColor(polylineStrokeColor.cgColor)

            if self.lineWidth > 0 {
                context.setLineWidth(self.lineWidth*roadWidth)
            } else {
                context.setLineWidth(roadWidth)
            }
            context.setLineJoin(self.lineJoin)
            context.setLineCap(self.lineCap)
            context.setMiterLimit(self.miterLimit)
            
            // create path
            context.move(to: self.point(for: polylineMapPoints[0]))
            for element in 1 ..< polyline.pointCount {
                let point_ = self.point(for: polylineMapPoints[element])
                context.addLine(to: point_)
            }
            
            // draw previously created path
            context.drawPath(using: .stroke)
            
        }
        
        context.restoreGState()

    }
    
}

该代码使用了一个小助手:

public extension MKMultiPoint {
    var coordinates: [CLLocationCoordinate2D] {
        var coords = [CLLocationCoordinate2D](repeating: kCLLocationCoordinate2DInvalid, count: pointCount)
        getCoordinates(&coords, range: NSRange(location: 0, length: pointCount))
        return coords
    }
}

这是测试数据在我的游客应用程序中的样子:

© www.soinside.com 2019 - 2024. All rights reserved.