我提出的想法之一是创建一个 CGPath 并在每次使用渐变时对其进行描边drawMapRect
方法被调用,因为MKPolylineView
被替换为MKPlolylineRenderer
在ios7中。
我尝试通过子类化来实现这个MKOverlayPathRenderer
但我没能找出单独的CGPath,然后我发现了一个神秘的方法,名为-(void) strokePath:(CGPathRef)path inContext:(CGContextRef)context
这听起来像我需要的,但如果你重写你的方法时不调用 super 方法,它就不会被调用drawMapRect
.
这就是我现在正在努力的。
我会继续尝试,所以如果我解决了一些问题,我会回来更新答案。
=========UPDATE=================================================
这就是我这些天所解决的问题,我几乎实现了上面提到的基本想法,但是是的,我仍然无法根据特定的mapRect挑选出单独的路径,所以我只是在所有路径的boundingBox与当前mapRect相交。糟糕的技巧,但现在可以使用。
In the -(void) drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
渲染类中的方法,我这样做:
CGMutablePathRef fullPath = CGPathCreateMutable();
BOOL pathIsEmpty = YES;
//merging all the points as entire path
for (int i=0;i< polyline.pointCount;i++){
CGPoint point = [self pointForMapPoint:polyline.points[i]];
if (pathIsEmpty){
CGPathMoveToPoint(fullPath, nil, point.x, point.y);
pathIsEmpty = NO;
} else {
CGPathAddLineToPoint(fullPath, nil, point.x, point.y);
}
}
//get bounding box out of entire path.
CGRect pointsRect = CGPathGetBoundingBox(fullPath);
CGRect mapRectCG = [self rectForMapRect:mapRect];
//stop any drawing logic, cuz there is no path in current rect.
if (!CGRectIntersectsRect(pointsRect, mapRectCG))return;
然后我逐点分割整个路径以单独绘制其渐变。
请注意,hues
包含映射每个位置速度的色调值的数组。
for (int i=0;i< polyline.pointCount;i++){
CGMutablePathRef path = CGPathCreateMutable();
CGPoint point = [self pointForMapPoint:polyline.points[i]];
ccolor = [UIColor colorWithHue:hues[i] saturation:1.0f brightness:1.0f alpha:1.0f];
if (i==0){
CGPathMoveToPoint(path, nil, point.x, point.y);
} else {
CGPoint prevPoint = [self pointForMapPoint:polyline.points[i-1]];
CGPathMoveToPoint(path, nil, prevPoint.x, prevPoint.y);
CGPathAddLineToPoint(path, nil, point.x, point.y);
CGFloat pc_r,pc_g,pc_b,pc_a,
cc_r,cc_g,cc_b,cc_a;
[pcolor getRed:&pc_r green:&pc_g blue:&pc_b alpha:&pc_a];
[ccolor getRed:&cc_r green:&cc_g blue:&cc_b alpha:&cc_a];
CGFloat gradientColors[8] = {pc_r,pc_g,pc_b,pc_a,
cc_r,cc_g,cc_b,cc_a};
CGFloat gradientLocation[2] = {0,1};
CGContextSaveGState(context);
CGFloat lineWidth = CGContextConvertSizeToUserSpace(context, (CGSize){self.lineWidth,self.lineWidth}).width;
CGPathRef pathToFill = CGPathCreateCopyByStrokingPath(path, NULL, lineWidth, self.lineCap, self.lineJoin, self.miterLimit);
CGContextAddPath(context, pathToFill);
CGContextClip(context);//<--clip your context after you SAVE it, important!
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocation, 2);
CGColorSpaceRelease(colorSpace);
CGPoint gradientStart = prevPoint;
CGPoint gradientEnd = point;
CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient);
CGContextRestoreGState(context);//<--Don't forget to restore your context.
}
pcolor = [UIColor colorWithCGColor:ccolor.CGColor];
}
这就是所有核心绘图方法,当然你需要points
, velocity
在您的覆盖类中并使用 CLLocationManager 提供它们。
最后一点是如何得到hue
值出速度,嗯,我发现如果色调范围从0.03~0.3正好代表从红色到绿色,所以我做了一些按比例映射到色调和速度。
最后的最后,这里是这个演示的完整源代码:https://github.com/wdanxna/GradientPolyline https://github.com/wdanxna/GradientPolyline
如果看不到您绘制的线,请不要惊慌,我只是将地图区域定位在我的位置:)