Polyligne de dégradé avec MapKit ios

J'essaie de tracer une route sur un MKMapView en utilisant des superpositions (MKOverlay). Cependant, en fonction de la vitesse actuelle, je veux faire quelque chose comme l'application Nike avec un dégradé en traçant la route, si la couleur change (par exemple, du vert à l'orange si un user roule de 65 mph à 30 mph).

Voici une capture d'écran de ce que je veux:

image de superposition de dégradé

Donc, tous les 20 mètres, j'ajoute une superposition de l'ancienne à la nouvelle en utilisant:

// 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; 

Fondamentalement, j'ajoute beaucoup de petites superpositions. Ensuite, je voudrais créer le dégradé sur ce petit dessin au trait, donc j'essaye de le faire dans le délégué overlay:

 - (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; } 

J'essaie d'append le dégradé de cette façon, mais je suppose que ce n'est pas la façon de le faire parce que je ne peux pas le faire fonctionner.

Je peux également tracer l'itinéraire chaque fois qu'il y a une mise à jour sur l'location de l'user (dans le délégué de l'object de localization), ou comme ci-dessus tous les 20 mètres.

Pouvez-vous s'il vous plaît m'aider sur celui-là, en me donnant des conseils! Merci!

    L'une des idées que j'ai émises est de créer un CGPath et de le bash avec un dégradé à chaque fois que la méthode drawMapRect été appelée, puisque MKPolylineView est remplacé par MKPlolylineRenderer dans ios7.

    J'ai essayé d'implémenter ceci en sous- MKOverlayPathRenderer un MKOverlayPathRenderer mais j'ai échoué à choisir CGPath individuel, alors je trouve une méthode mystérieuse nommée -(void) strokePath:(CGPathRef)path inContext:(CGContextRef)context qui ressemble à ce dont j'ai besoin, mais ne sera pas appelé si vous n'appelez pas la super méthode lorsque vous drawMapRect votre drawMapRect .

    C'est ce que je travaille pour l'instant.

    Je vais continuer à essayer, donc si je travaille sur quelque chose je reviendrai et mettra à jour la réponse.

    ========= MISE À JOUR ==================================== ========

    entrez la description de l'image ici

    Donc, c'est ce que je suis en train de faire ces jours-ci, j'ai presque implémenté l'idée de base mentionnée ci-dessus mais oui, je ne peux toujours pas choisir un PATH spécifique selon mapRect, donc je dessine tous les paths avec gradient en même time. boundingBox de tous les paths croise le mapRect actuel. mauvais tour, mais travaillez pour le moment.

    Dans le -(void) drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context méthode de -(void) drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context dans la class de rendu, je fais ceci:

     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; 

    Ensuite, je divise le path entier point par point pour dessiner son dégradé individuellement. notez que le tableau des hues contenant la valeur de teinte mappant chaque vitesse d'location.

     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]; } 

    C'est toute la méthode de dessin de base et bien sûr vous avez besoin de points , de velocity dans votre class de superposition et de les nourrir avec CLLocationManager.

    le dernier point est comment get la valeur de la hue hors de la vitesse, eh bien, j'ai trouvé que si la teinte allant de 0.03 ~ 0.3 est exactement du rouge au vert, donc je fais un peu de correspondance proportionnelle à la teinte et la vélocité.

    dernier de la dernière, ici vous êtes c'est la source complète de cette démo: https://github.com/wdanxna/GradientPolyline

    ne paniquez pas si vous ne voyez pas la ligne que vous dessinez, je positionne juste la région de la carte sur ma position 🙂

    Il me semble que votre drawRect dans la vue de dessin au trait manque le réglage du dégradé. le dessin peut se produire sur un fil différent pour les superpositions. s'il vous plaît postr le code.