Ios 覆盖层。在上面的MKMapView委托函数中,我根据标准创建视图,并尝试向其添加渐变。请参阅我文章中的代码,我对其进行了更新。我有一个函数,每20米添加一次从A点到B点的叠加,然后我在地图视图代理中创建叠加视图时尝试添加渐变层。您的逻辑似乎是错误的。不能像
Ios 覆盖层。在上面的MKMapView委托函数中,我根据标准创建视图,并尝试向其添加渐变。请参阅我文章中的代码,我对其进行了更新。我有一个函数,每20米添加一次从A点到B点的叠加,然后我在地图视图代理中创建叠加视图时尝试添加渐变层。您的逻辑似乎是错误的。不能像,ios,mkmapview,overlay,mapkit,gradient,Ios,Mkmapview,Overlay,Mapkit,Gradient,覆盖层。在上面的MKMapView委托函数中,我根据标准创建视图,并尝试向其添加渐变。请参阅我文章中的代码,我对其进行了更新。我有一个函数,每20米添加一次从A点到B点的叠加,然后我在地图视图代理中创建叠加视图时尝试添加渐变层。您的逻辑似乎是错误的。不能像这样向覆盖添加渐变层。相反,您必须有一种方法来构建和绘制具有不同阴影的各个分段的整个路径。WWDC2010示例代码(“面包屑”)演示了这一点。您当前的方法无法工作,因为您只是第一次将路径段添加为新的子层。但随着时间的推移,这将导致图层树变得非常
覆盖层。在上面的MKMapView委托函数中,我根据标准创建视图,并尝试向其添加渐变。请参阅我文章中的代码,我对其进行了更新。我有一个函数,每20米添加一次从A点到B点的叠加,然后我在地图视图代理中创建叠加视图时尝试添加渐变层。您的逻辑似乎是错误的。不能像这样向覆盖添加渐变层。相反,您必须有一种方法来构建和绘制具有不同阴影的各个分段的整个路径。WWDC2010示例代码(“面包屑”)演示了这一点。您当前的方法无法工作,因为您只是第一次将路径段添加为新的子层。但随着时间的推移,这将导致图层树变得非常大。您需要能够在一层中绘制整个路径。好的,谢谢@cocoanatics,我将查看它并让您不断更新!我找不到示例代码,我试图在苹果的网站上查找,等等,也无法登录WWDC,因为我还没有买票。你能给我这个资源吗?谢谢通过进入iTunes中的WWDC 2010视频网站-然后在右下角的链接下,有一个下载所有示例源代码的链接。刚刚看到了您的答案。我认为这正是我在这个问题上需要达到的目标:。基本上,如果我理解正确,您可以手动逐段重新创建路径,并通过每次剪切仅对当前添加的路径应用渐变。这是否足够理想/快速?首先,我尝试使用一个渐变对象绘制整个路径,该对象在
gradientColors
中具有我需要的所有颜色值,并且每个颜色值映射我的gradientLocation
中的一个位置值。我认为这应该管用,但它不(奇怪)。文件说我们不应该从当前的MapRect中画出任何东西,似乎一次画出整个路径不是一个选项?所以我认为把它分成几个部分是最简单的方法。。。说到优化,它在我的iPhone中运行正常:)但还有一些需要改进的地方,比如:只画与当前MapRect相交的线。我根据您的代码和github示例实现了我的东西,效果非常好。我建议的唯一更改是直接在init中准备路径,只在drawRect
中使用,或者只使用CGRect pointsR=[self-rectformprect:polyline.boundingMapRect]代码>并检查CGRectContains,而不仅仅是交叉点。我的问题仍然没有答案,而且有悬赏。你可以把答案贴在上面,我很乐意接受,这对我帮助很大:)
// Create a c array of points.
MKMapPoint *pointsArray = malloc(sizeof(CLLocationCoordinate2D) * 2);
// Create 2 points.
MKMapPoint startPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(oldLatitude, oldLongitude));
MKMapPoint endPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(newLatitude, newLongitude));
// Fill the array.
pointsArray[0] = startPoint;
pointsArray[1] = endPoint;
// Erase polyline and polyline view if not nil.
if (self.routeLine != nil)
self.routeLine = nil;
if (self.routeLineView != nil)
self.routeLineView = nil;
// Create the polyline based on the array of points.
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];
// Add overlay to map.
[self.mapView addOverlay:self.routeLine];
// clear the memory allocated earlier for the points.
free(pointsArray);
// Save old coordinates.
oldLatitude = newLatitude;
oldLongitude = newLongitude;
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine) {
// If we have not yet created an overlay view for this overlay, create it now.
if(self.routeLineView == nil) {
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
if (speedMPH < 25.0) {
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
}
else if (speedMPH >= 25.0 && speedMPH < 50.0) {
self.routeLineView.fillColor = [UIColor orangeColor];
self.routeLineView.strokeColor = [UIColor orangeColor];
}
else {
self.routeLineView.fillColor = [UIColor greenColor];
self.routeLineView.strokeColor = [UIColor greenColor];
}
// Size of the trace.
self.routeLineView.lineWidth = routeLineWidth;
// Add gradient if color changed.
if (oldColor != self.routeLineView.fillColor) {
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.routeLineView.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[oldColor CGColor], (id)[self.routeLineView.fillColor CGColor], nil];
[self.routeLineView.layer insertSublayer:gradient atIndex:0];
}
// Record old color for gradient.
if (speedMPH < 25.0)
oldColor = [UIColor redColor];
else if (speedMPH >= 25.0 && speedMPH < 50.0)
oldColor = [UIColor orangeColor];
else
oldColor = [UIColor greenColor];
}
overlayView = self.routeLineView;
}
return overlayView;
}
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;
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];
}
class GradientPolyline: MKPolyline {
var hues: [CGFloat]?
public func getHue(from index: Int) -> CGColor {
return UIColor(hue: (hues?[index])!, saturation: 1, brightness: 1, alpha: 1).cgColor
}
}
extension GradientPolyline {
convenience init(locations: [CLLocation]) {
let coordinates = locations.map( { $0.coordinate } )
self.init(coordinates: coordinates, count: coordinates.count)
let V_MAX: Double = 5.0, V_MIN = 2.0, H_MAX = 0.3, H_MIN = 0.03
hues = locations.map({
let velocity: Double = $0.speed
if velocity > V_MAX {
return CGFloat(H_MAX)
}
if V_MIN <= velocity || velocity <= V_MAX {
return CGFloat((H_MAX + ((velocity - V_MIN) * (H_MAX - H_MIN)) / (V_MAX - V_MIN)))
}
if velocity < V_MIN {
return CGFloat(H_MIN)
}
return CGFloat(velocity)
})
}
}
class GradidentPolylineRenderer: MKPolylineRenderer {
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
let boundingBox = self.path.boundingBox
let mapRectCG = rect(for: mapRect)
if(!mapRectCG.intersects(boundingBox)) { return }
var prevColor: CGColor?
var currentColor: CGColor?
guard let polyLine = self.polyline as? GradientPolyline else { return }
for index in 0...self.polyline.pointCount - 1{
let point = self.point(for: self.polyline.points()[index])
let path = CGMutablePath()
currentColor = polyLine.getHue(from: index)
if index == 0 {
path.move(to: point)
} else {
let prevPoint = self.point(for: self.polyline.points()[index - 1])
path.move(to: prevPoint)
path.addLine(to: point)
let colors = [prevColor!, currentColor!] as CFArray
let baseWidth = self.lineWidth / zoomScale
context.saveGState()
context.addPath(path)
let gradient = CGGradient(colorsSpace: nil, colors: colors, locations: [0, 1])
context.setLineWidth(baseWidth)
context.replacePathWithStrokedPath()
context.clip()
context.drawLinearGradient(gradient!, start: prevPoint, end: point, options: [])
context.restoreGState()
}
prevColor = currentColor
}
}
}
let runRoute = GradientPolyline(locations: locations)
self.mapView.addOverlay(runRoute)
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is GradientPolyline {
let polyLineRender = GradientMKPolylineRenderer(overlay: overlay)
polyLineRender.lineWidth = 7
return polyLineRender
}
}