2011-12-30 51 views
10

iOS 5 thay đổi cách built-in Google App Maps vẽ các tuyến đường:Vẽ MKMapView Overlay như Chỉ Google Maps

Apple's line

bây giờ tôi muốn sao chép thiết kế của lớp phủ đường trong ứng dụng của riêng tôi nhưng hiện tại tôi chỉ có thể vẽ một đường thẳng màu xanh. Tôi muốn thêm hiệu ứng 3D với gradient, đường viền và ánh sáng. Bất kỳ ý tưởng về cách thực hiện điều này?

Hiện nay tôi đang sử dụng đoạn mã sau:

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

Hệ quả là một dòng khá xấu xí:

my line

Cảm ơn!

Cập nhật: Giải pháp sẽ hoạt động trên iOS 4.0 trở lên.

+0

Bạn có thể đăng mã bạn đang sử dụng để vẽ đường không? –

+0

@sudo rm -rf: Tôi đã thêm mã vẽ. – myell0w

Trả lời

7

Tôi nghĩ rằng @ChrisMiles là chính xác trong đó các phân đoạn có thể được vẽ riêng lẻ. (Ban đầu tôi nghĩ rằng điều này có thể là doable bằng cách sử dụng CGPatternRef nhưng bạn không có bất kỳ quyền truy cập vào CTM hoặc điểm cuối đường dẫn bên trong mẫu vẽ gọi lại.)

Với điều này trong tâm trí, đây là một cực kỳ thô, back- ví dụ về phong bì của cách bạn có thể bắt đầu một nỗ lực như vậy (điền các phân đoạn riêng lẻ). Lưu ý rằng:

  • màu gradient được đoán
  • mũ cuối là không tồn tại và sẽ cần phải được thực hiện riêng rẽ
  • một số đồ tạo tác răng cưa vẫn
  • không rất nhiều sự chú ý đã được trả tiền để thực hiện

Hy vọng điều này có thể giúp bạn bắt đầu ít nhất (và hoạt động thông qua một số hình học phân tích).

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

Tôi sẽ nói rằng họ đang vẽ một CGPath xung quanh dòng ban đầu, vuốt ve các cạnh và tô màu tô nó. Các đầu được giới hạn bằng cách thêm một vòng tròn bán cho CGPath.

Sẽ có nhiều công việc hơn là chỉ vẽ một dòng và vuốt nó, nhưng cho phép chúng kiểm soát hoàn toàn kiểu dáng của đường dẫn được hiển thị.

+0

Điều đó nghe có vẻ đúng về Chris, cảm ơn. Vấn đề của tôi là làm thế nào để vẽ một gradient dọc theo một CGPath. Bất kỳ ý tưởng hoặc đoạn mã nào bạn có thể chia sẻ? – myell0w

+0

Tôi không biết kết quả sẽ trông như thế nào, nhưng bạn có thể sử dụng 'CGContextReplacePathWithStrokedPath()' để lấy một phác thảo, sau đó bạn có thể điền vào với một gradient. Câu hỏi trước này có thể hữu ích: http://stackoverflow.com/questions/2737973/on-osx-how-do-i-gradient-fill-a-path-stroke – lxt

+0

Sau một chút thử nghiệm, tôi không thể tìm thấy cách để dễ dàng có được một tô màu gradient để đi theo một con đường, theo cách mà họ đang làm nó. Họ có thể đang phá vỡ con đường và vẽ một tô màu gradient cho từng phân đoạn riêng biệt. –

Các vấn đề liên quan