与MapKit ios的渐变折线
我试图使用覆盖(MKOverlay)跟踪MKMapView上的路线。 但是,根据目前的速度,如果颜色正在改变(例如,如果用户从65英里/小时到30英里/小时的速度从绿色变为橙色),则我想在跟踪路线时使用具有渐变的耐克应用程序。
以下是我想要的截图:
所以,每隔20米,我就使用以下方法从旧坐标到新坐标添加覆盖图:
// Create ac 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;
基本上我添加了很多小覆盖。 然后我想在这个小的线条图上创build渐变,所以我试图在叠加代理中这样做:
- (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; }
我试图以这种方式添加渐变,但我想这不是这样做的方式,因为我不能让它工作。
每当用户位置更新(位置对象的代表)时,我也可以跟踪路线,或者每20米以上跟踪路线。
你能帮我一下,给我提示! 谢谢!
我想到的一个想法是创build一个CGPath,并在每次调用drawMapRect
方法时使用渐变对其进行描边,因为MKPolylineView
被MKPlolylineRenderer
中的MKPolylineView
所取代。
我试图通过MKOverlayPathRenderer
一个MKOverlayPathRenderer
来实现,但是我没有select出个别的CGPath,于是我find了一个名为-(void) strokePath:(CGPathRef)path inContext:(CGContextRef)context
的神秘方法,这听起来像我所需要的,但是它如果您在覆盖drawMapRect
时不调用超级方法,将不会被调用。
那就是我现在正在做的事情。
我会继续努力,所以如果我找出一些东西,我会回来,并更新答案。
========= 更新 ======================================== ========
所以这就是我现在所做的,几乎实现了上面提到的基本思想,但是,我仍然不能根据具体的mapRect挑选出一个单独的PATH,所以我只是在所有path的boundingBox与当前mapRect相交。 可恶的伎俩,但现在工作。
在-(void) drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
在渲染类中的-(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;
然后,我将整个path逐点分开,逐个绘制其渐变。 注意包含色相值的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
速度中得到hue
值,好吧,我发现如果0.03〜0.3的色调恰恰是从红色到绿色的,那么我会按比例映射到色调和速度。
最后一个,在这里你是这个演示的完整源代码: https : //github.com/wdanxna/GradientPolyline
不要惊慌,如果看不到你画的线,我只是把地图区域放在我的位置:)
听起来你的绘图视图中的drawRect缺less渐变的设置。 绘图可能会在叠加层的不同线程上发生。 请张贴代码。