Comments (4)
Hi there! Thanks, it's so cool to see people using something I've made! I'm actually doing the exact thing you ask in one of my apps so I can help you on this one. What you want to do is calculate a hue value for each point based on your elevation data, and create a gradient between the previous point's colour and the current point's colour in the drawMapRect function, for each part of the path.
Here's the class I made so you can see how I've done it. I might add it to this repo if it's something lots of people want.
//
// PedalPathRenderer.swift
// Pedal
//
// Created by Joel Trew on 24/04/2016.
//
import MapKit
class PedalPathElevationRenderer: MKOverlayPathRenderer {
var polyline : MKPolyline
var elevations: [Int]
var maxElevation: Int?
var border: Bool = false
var borderColor: UIColor?
//MARK: Initializers
init(polyline: MKPolyline, elevations: [Int]) {
self.polyline = polyline
self.elevations = elevations
super.init(overlay: polyline)
self.maxElevation = calculateMaxElevation()
}
//MARK: Override methods
override func drawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale, inContext context: CGContext) {
var baseWidth: CGFloat
if zoomScale > 0.1 {
baseWidth = self.lineWidth * 2
} else {
baseWidth = self.lineWidth / zoomScale
}
/*
Set path width relative to map zoom scale
*/
var firstColor:UIColor = UIColor(hue: self.getHueFor(elevation: elevations[0]), saturation: 1, brightness: 1, alpha: 1)
var lastColor: UIColor = UIColor(hue: self.getHueFor(elevation: elevations[1]), saturation: 1, brightness: 1, alpha: 1)
if self.border {
CGContextSetLineWidth(context, baseWidth * 1.5)
CGContextSetLineJoin(context, CGLineJoin.Round)
CGContextSetLineCap(context, CGLineCap.Round)
CGContextAddPath(context, self.path)
CGContextSetStrokeColorWithColor(context, self.borderColor?.CGColor ?? UIColor.whiteColor().CGColor)
CGContextStrokePath(context)
}
for i in 0...self.polyline.pointCount-1 {
let point: CGPoint = pointForMapPoint(self.polyline.points()[i])
let path: CGMutablePathRef = CGPathCreateMutable()
lastColor = UIColor(hue: self.getHueFor(elevation: elevations[i]), saturation: 1, brightness: 1, alpha: 1)
if i==0 {
CGPathMoveToPoint(path, nil, point.x, point.y)
} else {
let previousPoint = self.pointForMapPoint(polyline.points()[i-1])
CGPathMoveToPoint(path, nil, previousPoint.x, previousPoint.y)
CGPathAddLineToPoint(path, nil, point.x, point.y)
CGContextSaveGState(context);
let colorspace = CGColorSpaceCreateDeviceRGB()
let locations: [CGFloat] = [0,1]
let gradient = CGGradientCreateWithColors(colorspace, [firstColor.CGColor, lastColor.CGColor], locations)
let pathToFill = CGPathCreateCopyByStrokingPath(path, nil, baseWidth, CGLineCap.Round, CGLineJoin.Round, self.miterLimit)
CGContextAddPath(context, pathToFill)
CGContextClip(context);
let gradientStart = previousPoint;
let gradientEnd = point;
CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, CGGradientDrawingOptions.DrawsBeforeStartLocation);
CGContextRestoreGState(context)
}
firstColor = UIColor(CGColor: lastColor.CGColor)
}
super.drawMapRect(mapRect, zoomScale: zoomScale, inContext: context)
}
/*
Create path from polyline
Thanks to Adrian Schoenig
(http://adrian.schoenig.me/blog/2013/02/21/drawing-multi-coloured-lines-on-an-mkmapview/ )
*/
override func createPath() {
let path: CGMutablePathRef = CGPathCreateMutable()
var pathIsEmpty: Bool = true
for i in 0...self.polyline.pointCount-1 {
let point: CGPoint = pointForMapPoint(self.polyline.points()[i])
if pathIsEmpty {
CGPathMoveToPoint(path, nil, point.x, point.y)
pathIsEmpty = false
} else {
CGPathAddLineToPoint(path, nil, point.x, point.y)
}
}
self.path = path
}
private func getHueFor(elevation elevation: Int) -> CGFloat {
let maxElevation = CGFloat(self.maxElevation ?? 50)
let hue = CGFloat(elevation).map(from: 0...maxElevation+5, to: 0.0...0.4)
return 0.4-hue
}
private func calculateMaxElevation() -> Int {
return self.elevations.maxElement() ?? 0
}
}
extension CGFloat {
func map(from from: ClosedInterval<CGFloat>, to: ClosedInterval<CGFloat>) -> CGFloat {
let result = ((self - from.start) / (from.end - from.start)) * (to.end - to.start) + to.start
return result
}
}
Hopefully this will help you out with your issue. 😄
- Joel
from gradientpathrenderer.
Thanks for your answer. I did a similar coding. It's working but each drawMapRect call will create multiples CGPath, the map reactivity slow down, the memory increase a lot and on iPad 2 (512 MB), some memory warning come fast. I have some GPX traces with a lot of points (~1000), so for now, i'm searching for a lighter solution.
Thanks again and happy coding :)
from gradientpathrenderer.
Ok good luck :) , you're welcome to share your solution here if you find a better way
from gradientpathrenderer.
@NasH5169 What's the solution, can you share it to me. Thanks
from gradientpathrenderer.
Related Issues (5)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gradientpathrenderer.