2011-12-30 13 views
10

iOS 5 रास्ता निर्मित गूगल मैप्स एप ड्रॉ मार्गों बदल दिया है:आहरण MKMapView ओवरले

Apple's line

अब मैं अपने स्वयं के अनुप्रयोग में मार्ग ओवरले के डिजाइन को दोहराने के लिए चाहते हैं लेकिन मैं वर्तमान में केवल एक सादे नीली रेखा खींचने में सक्षम हूं। मैं ढाल, सीमाओं और चमक के साथ 3 डी प्रभाव जोड़ना चाहता हूं। इसे पूरा करने के तरीके पर कोई विचार?

वर्तमान में मैं निम्नलिखित कोड का उपयोग कर रहा:

CGContextSetFillColorWithColor(context, fillColor.CGColor); 
CGContextSetLineJoin(context, kCGLineJoinRound); 
CGContextSetLineCap(context, kCGLineCapRound); 
CGContextSetLineWidth(context, lineWidth); 
CGContextAddPath(context, path); 
CGContextReplacePathWithStrokedPath(context); 
CGContextFillPath(context); 

एक नहीं बल्कि बदसूरत लाइन में परिणामी:

my line

धन्यवाद!

अद्यतन: समाधान आईओएस 4.0 और ऊपर काम करना चाहिए।

+0

क्या आप वर्तमान में कोड खींचने वाले कोड को पोस्ट करने में सक्षम हैं? –

+0

@sudo rm -rf: मैंने ड्राइंग कोड जोड़ा है। – myell0w

उत्तर

7

मुझे लगता है कि @ChrisMiles सही है कि सेगमेंट शायद व्यक्तिगत रूप से खींचे जा रहे हैं। (मैंने शुरू में सोचा था कि यह CGPatternRef का उपयोग कर करने योग्य हो सकता है लेकिन आपके पास पैटर्न ड्राइंग कॉलबैक के अंदर सीटीएम या पथ अंत बिंदुओं तक कोई पहुंच नहीं है।)

इस बात को ध्यान में रखते हुए, यहां एक बहुत ही कच्ची, बैक- इस तरह के प्रयास (आप व्यक्तिगत रूप से सेगमेंट भरना) शुरू करने के बारे में लिफाफा उदाहरण। ध्यान दें कि:

  • ढाल रंग अनुमान लगाया जाता है
  • अंत टोपियां अस्तित्वहीन कर रहे हैं और अलग से लागू किया जाना
  • कुछ अलियासिंग कलाकृतियों
  • रहने के ध्यान के एक महान सौदा प्रदर्शन करने के लिए भुगतान किया गया था नहीं की आवश्यकता होगी

उम्मीद है कि यह आपको कम से कम शुरू कर सकता है (और कुछ विश्लेषणात्मक ज्यामिति के माध्यम से काम करता है)।

- (CGGradientRef)lineGradient 
{ 
    static CGGradientRef gradient = NULL; 
    if (gradient == NULL) { 
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
     CGColorRef white = [[UIColor colorWithWhite:1.f 
               alpha:0.7f] CGColor]; 
     CGColorRef blue = [[UIColor colorWithRed:0.1f 
              green:0.2f 
              blue:1.f 
              alpha:0.7f] CGColor]; 
     CGColorRef lightBlue = [[UIColor colorWithRed:0.4f 
               green:0.6f 
               blue:1.f 
               alpha:0.7f] CGColor]; 
     CFMutableArrayRef colors = CFArrayCreateMutable(kCFAllocatorDefault, 
                 8, 
                 NULL); 
     CFArrayAppendValue(colors, blue); 
     CFArrayAppendValue(colors, blue); 
     CFArrayAppendValue(colors, white); 
     CFArrayAppendValue(colors, white); 
     CFArrayAppendValue(colors, lightBlue); 
     CFArrayAppendValue(colors, lightBlue); 
     CFArrayAppendValue(colors, blue); 
     CFArrayAppendValue(colors, blue); 
     CGFloat locations[8] = {0.f, 0.08f, 0.14f, 0.21f, 0.29f, 0.86f, 0.93f, 1.f}; 
     gradient = CGGradientCreateWithColors(colorSpace, 
               colors, 
               locations); 
     CFRelease(colors); 
     CGColorSpaceRelease(colorSpace); 
    } 
    return gradient; 
} 

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSaveGState(context); 

    CGContextSetAllowsAntialiasing(context, YES); 
    CGContextSetShouldAntialias(context, YES); 

    // Fill background color 
    [[UIColor whiteColor] setFill]; 
    UIRectFill(rect); 

    // Build a path 
    CGFloat strokeWidth = 10.f; 
    CGContextSetLineWidth(context, strokeWidth); 

    CGGradientRef gradient = [self lineGradient]; 

    CGPoint points[9] = { 
     CGPointMake(10.f, 25.f), 
     CGPointMake(100.f, 100.f), 
     CGPointMake(100.f, 150.f), 
     CGPointMake(22.f, 300.f), 
     CGPointMake(230.f, 400.f), 
     CGPointMake(230.f, 200.f), 
     CGPointMake(300.f, 200.f), 
     CGPointMake(310.f, 160.f), 
     CGPointMake(280.f, 100.f) 
    }; 


    for (NSUInteger i = 1; i < 9; i++) { 
     CGPoint start = points[i - 1]; 
     CGPoint end = points[i]; 
     CGFloat dy = end.y - start.y; 
     CGFloat dx = end.x - start.x; 
     CGFloat xOffset, yOffset; 
     // Remember that, unlike Cartesian geometry, origin is in *upper* left! 
     if (dx == 0) { 
      // Vertical to start, gradient is horizontal 
      xOffset = 0.5 * strokeWidth; 
      yOffset = 0.f; 
      if (dy < 0) { 
       xOffset *= -1; 
      } 
     } 
     else if (dy == 0) { 
      // Horizontal to start, gradient is vertical 
      xOffset = 0.f; 
      yOffset = 0.5 * strokeWidth; 
     } 
     else { 
      // Sloped 
      CGFloat gradientSlope = - dx/dy; 
      xOffset = 0.5 * strokeWidth/sqrt(1 + gradientSlope * gradientSlope); 
      yOffset = 0.5 * strokeWidth/sqrt(1 + 1/(gradientSlope * gradientSlope)); 
      if (dx < 0 && dy > 0) { 
       yOffset *= -1; 
      } 
      else if (dx > 0 && dy < 0) { 
       xOffset *= -1; 
      } 
      else if (dx < 0 && dy < 0) { 
       yOffset *= -1; 
       xOffset *= -1; 
      } 
      else { 
      } 
     } 
     CGAffineTransform startTransform = CGAffineTransformMakeTranslation(-xOffset, yOffset); 
     CGAffineTransform endTransform = CGAffineTransformMakeTranslation(xOffset, -yOffset); 
     CGPoint gradientStart = CGPointApplyAffineTransform(start, startTransform); 
     CGPoint gradientEnd = CGPointApplyAffineTransform(start, endTransform); 

     CGContextSaveGState(context); 
     CGContextMoveToPoint(context, start.x, start.y); 
     CGContextAddLineToPoint(context, end.x, end.y); 
     CGContextReplacePathWithStrokedPath(context); 
     CGContextClip(context); 
     CGContextDrawLinearGradient(context, 
            gradient, 
            gradientStart, 
            gradientEnd, 
            kCGGradientDrawsAfterEndLocation | kCGGradientDrawsBeforeStartLocation); 
     CGContextRestoreGState(context); 
    } 

    CGContextRestoreGState(context); 
} 
1

मैं कहूंगा कि वे मूल रेखा के चारों ओर एक CGPath ड्राइंग कर रहे हैं, किनारों और ढाल को भरकर इसे भर रहे हैं। सीजीपाथ में अर्द्ध सर्कल जोड़कर सिरों को कैप्ड किया जाता है।

केवल एक पंक्ति खींचने और इसे पथभ्रष्ट करने से थोड़ा अधिक काम होगा, लेकिन उन्हें प्रस्तुत पथ की शैली पर पूर्ण नियंत्रण देता है।

+0

यह सही क्रिस के बारे में लगता है, धन्यवाद। मेरी समस्या यह है कि एक CGPath के साथ ढाल कैसे आकर्षित करें। कोई विचार या कोड स्निपेट जो आप साझा कर सकते हैं? – myell0w

+0

मुझे नहीं पता कि परिणाम कैसा दिखेंगे, लेकिन आप एक सीधी रेखा को पुनः प्राप्त करने के लिए 'CGContextReplacePathWithStrokedPath()' का उपयोग कर सकते हैं, जिसे आप ढाल के साथ भर सकते हैं। यह पिछला प्रश्न उपयोगी हो सकता है: http://stackoverflow.com/questions/2737973/on-osx-how-do-i-gradient-fill-a-path-stroke – lxt

+0

कुछ प्रयोग के बाद मुझे कोई नहीं मिला एक मार्ग का पालन करने के लिए आसानी से ढाल भरने का तरीका, जिस तरह से वे इसे कर रहे हैं। वे पथ को तोड़ सकते हैं और प्रत्येक सेगमेंट के लिए अलग-अलग ग्रेडियेंट भर सकते हैं। –