GradientPolyLineRender

import Foundation
import MapKit

class GradientPolyLineRender: MKOverlayPathRenderer {
var hues: [CGFloat] = []
var polyline: GSGradientPolyline?

var rwLock: pthread_rwlock_t = pthread_rwlock_t()

var maxVelocity: CGFloat
var minVelocity: CGFloat
var maxHue: CGFloat
var minHue: CGFloat

init(overlay: MKOverlay, maxVelocity: CGFloat = 5, minVelocity: CGFloat = 2, maxHue: CGFloat = 0.3, minHue: CGFloat = 0.03) {
    self.maxVelocity = maxVelocity
    self.minVelocity = minVelocity
    self.maxHue = maxHue
    self.minHue = minHue
    
    super.init(overlay: overlay)
    pthread_rwlock_init(&rwLock, nil)
    polyline = self.overlay as? GSGradientPolyline
    createPath()
}

override func createPath() {
    guard var points = polyline?.points() else { return }
    let path = CGMutablePath()
    var pathIsEmpty: Bool = true
    let pointCount = polyline?.pointCount ?? 0
    for _ in 0 ..< pointCount {
        let point = self.point(for: points.pointee)
        if (pathIsEmpty){
            path.move(to: CGPoint(x: point.x, y: point.y))
            pathIsEmpty = false
        } else {
            path.addLine(to: CGPoint(x: point.x, y: point.y))
        }
        points = points.successor()
    }
    pthread_rwlock_wrlock(&rwLock)
    self.path = path
    pthread_rwlock_unlock(&rwLock)
}

override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
    let pointsRect = self.path.boundingBox
    let mapCGRect = self.rect(for: mapRect)
    if !pointsRect.intersects(mapCGRect) {
        return
    }
    guard var points = polyline?.points() else {
        return
    }
    var preColor = UIColor.white
    var currentColor = UIColor.white
    let pointsCount: Int = polyline?.colors?.count ?? 0
    for index in 0 ..< pointsCount {
        let currentPoint = self.point(for: points.pointee)
        let path = CGMutablePath()
        currentColor = (polyline?.colors?[index]) ?? UIColor.red
        if index == 0 {
            path.move(to: currentPoint)
        } else {
            let prevPoint = self.point(for: points.predecessor().pointee)
            path.move(to: prevPoint)
            path.addLine(to: currentPoint)
            
            var pc_r: CGFloat = 0
            var pc_g: CGFloat = 0
            var pc_b: CGFloat = 0
            var pc_a: CGFloat = 0
            var cc_r: CGFloat = 0
            var cc_g: CGFloat = 0
            var cc_b: CGFloat = 0
            var cc_a: CGFloat = 0
            preColor.getRed(&pc_r, green: &pc_g, blue: &pc_b, alpha: &pc_a)
            currentColor.getRed(&cc_r, green: &cc_g, blue: &cc_b, alpha: &cc_a)
            
            let gradientColors = [pc_r, pc_g, pc_b, pc_a, cc_r, cc_g, cc_b, cc_a]
            context.saveGState()
            
            let lineWidth = context.convertToUserSpace(CGSize(width: self.lineWidth, height: self.lineWidth)).width
            let pathToFill = path.copy(strokingWithWidth: lineWidth, lineCap: self.lineCap, lineJoin: self.lineJoin, miterLimit: self.miterLimit)
            context.addPath(pathToFill)
            context.clip()
            let colorSpace = CGColorSpaceCreateDeviceRGB()
            let gradient = CGGradient.init(colorSpace: colorSpace, colorComponents: gradientColors, locations: [0, 1], count: 2)
            let gardientStart = prevPoint
            let gardientEnd = currentPoint
            context.drawLinearGradient(gradient!, start: gardientStart, end: gardientEnd, options: CGGradientDrawingOptions.drawsAfterEndLocation)
            context.restoreGState()
        }
        preColor = UIColor.init(cgColor: currentColor.cgColor)
        points = points.successor()
    }
}
}

你可能感兴趣的:(GradientPolyLineRender)