2013-09-07 58 views
5

Giống như vậy:Làm thế nào tôi có thể vẽ một bóng cong?

enter image description here

Tôi biết rằng điều này sẽ không làm việc với NSShadow, vẽ nó trong drawRect: sẽ chỉ làm việc tốt.

+0

Bạn đang áp dụng bóng nào? –

+0

@ Pétur Không có gì, tôi muốn vẽ nó bằng cách sử dụng 'NSGradient' hoặc một cái gì đó tương tự. Bạn hiểu ý tôi muốn nói gì không? – NSAddict

+0

Bạn đang nhắm đến một loại bóng đổ nào đó? –

Trả lời

5

Bạn có thể thực hiện việc này và nhiều loại bóng khác bằng cách sử dụng lớp Ảnh động Lõi và thuộc tính shadowPath. Cái bóng mà bạn đang mô tả có thể được thực hiện với một đường bóng hình elip.

enter image description here

Mã để tạo bóng này bên dưới. Bạn có thể điều chỉnh kích thước của hình elip để có hình dạng tròn hơn của bóng. Bạn cũng có thể tinh chỉnh vị trí, độ mờ đục, bán kính màu và mờ bằng cách sử dụng các thuộc tính bóng trên lớp.

self.wantsLayer = YES; 

NSView *viewWithRoundShadow = [[NSView alloc] initWithFrame:NSMakeRect(30, 30, 200, 100)]; 
[self addSubview:viewWithRoundShadow]; 

CALayer *backingLayer = viewWithRoundShadow.layer; 
backingLayer.backgroundColor = [NSColor orangeColor].CGColor; 

// Configure shadow 
backingLayer.shadowColor = [NSColor blackColor].CGColor; 
backingLayer.shadowOffset = CGSizeMake(0, -1.); 
backingLayer.shadowRadius = 5.0; 
backingLayer.shadowOpacity = 0.75; 

CGRect shadowRect = backingLayer.bounds; 
CGFloat shadowRectHeight = 25.; 
shadowRect.size.height = shadowRectHeight; 
// make narrow 
shadowRect = CGRectInset(shadowRect, 5, 0); 

backingLayer.shadowPath = CGPathCreateWithEllipseInRect(shadowRect, NULL); 

Chỉ cần để hiển thị một số ví dụ về bóng khác hơn có thể được tạo ra bằng cách sử dụng kỹ thuật tương tự; một con đường như thế này

enter image description here

sẽ tạo ra một cái bóng như thế này

enter image description here

+0

Điều này là tuyệt vời! Hãy để tôi thử nó ra tối nay và tôi sẽ lấy lại cho bạn – NSAddict

+0

Hoạt động hoàn hảo, cảm ơn một bó! – NSAddict

1

Tôi có thể giải thích cách thực hiện điều này bằng mã hoặc giải thích cách sử dụng công cụ tạo mã này cho bạn. Tôi chọn cái sau.

Image

Sử dụng PaintCode (demo miễn phí có sẵn, 1 giờ giới hạn mỗi phiên).

  1. Vẽ hình oval
  2. Vẽ hình chữ nhật cắt ngang đáy hình bầu dục.
  3. CMD nhấp vào cả hình chữ nhật và hình bầu dục, trong danh sách "Đối tượng" ở góc trên cùng bên trái.
  4. Nhấn nút Giao nhau trong Thanh công cụ.
  5. Chọn Bezier từ danh sách Đối tượng.
  6. Đặt Stroke của mình để "Không Stroke"
  7. Nhấp vào nút Gradient (nằm ở bên trái, bên dưới Inspector Selection)
  8. Nhấn vào nút "+"
  9. Thay đổi màu gradient để màu xám nhạt.
  10. Từ thanh tra lựa chọn, thay đổi phong cách Fill để "Gradient"
  11. Chọn Gradient: Linear

điều chỉnh gradient cho đến khi bạn hài lòng.

+0

Thú vị ở nhiều cấp độ. –

+0

Tôi đánh giá cao nỗ lực của bạn, nhưng điều này là xa những gì tôi cần. Bóng tôi cần không chỉ tiến triển từ trái sang phải, mà còn mờ dần từ trên xuống dưới. Điều này là không thể với 'NSGradient', đó là lý do tại sao tôi đang tìm cách tiếp cận khác. Tôi đã mua PaintCode một thời gian trước đây, nó cũng không cung cấp bất kỳ tính năng tương tự nào khác. – NSAddict

2

Nó hoàn hảo nhưng tôi nghĩ nó sẽ tạo ra loại bóng bạn đang tìm kiếm. Hãy nhớ rằng tôi đã để lại một gradient tuyến tính đơn giản tại chỗ từ một màu đen đến một màu rõ ràng. Quá tối, điều này sẽ không cung cấp cho bạn một bóng siêu thực tế trừ khi bạn tinh chỉnh các giá trị một chút. Bạn có thể muốn chơi với gradient bằng cách thêm nhiều vị trí hơn với các giá trị alpha khác nhau để có được bất kỳ bước nào bạn thích. Một số thử nghiệm có thể được yêu cầu nhưng các giá trị là tất cả để chơi với.

Theo đề xuất của bạn, đó là điều drawRect:(CGRect)rect. Chỉ cần tạo một giao diện tùy chỉnh và chỉ ghi đè lên nó:

- (void)drawRect:(CGRect)rect { 
    // Get the context 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Setup the gradient locations. We just want 0 and 1 as in the start and end of the gradient. 
    CGFloat locations[2] = { 0.0, 1.0 }; 

    // Setup the two colors for the locations. A plain black and a plain black with alpha 0.0 ;-) 
    CGFloat colors[8] = { 0.0f, 0.0f, 0.0f, 1.0f, // Start color 
          0.0f, 0.0f, 0.0f, 0.0f }; // End color 

    // Build the gradient 
    CGGradientRef gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), 
                   colors, 
                   locations, 
                   2); 

    // Load a transformation matrix that will squash the gradient in the current context 
    CGContextScaleCTM(context,1.0f,0.1f); 

    // Draw the gradient 
    CGContextDrawRadialGradient(context,         // The context 
           gradient,         // The gradient 
           CGPointMake(self.bounds.size.width/2,0.0f), // Starting point 
           0.0f,          // Starting redius 
           CGPointMake(self.bounds.size.width/2,0.0f), // Ending point 
           self.bounds.size.width/2,     // Ending radius 
           kCGGradientDrawsBeforeStartLocation);  // Options 

    // Release it an pray that everything was well written 
    CGGradientRelease(gradient); 
} 

Đây là cách nó trông giống như trên màn hình của tôi ...

Resulting shadow

Tôi chỉ đơn giản là đặt một hình ảnh chỉ hơn cái bóng nhưng bạn có thể dễ dàng kết hợp bóng với một hình ảnh nếu bạn phân lớp UIImageView và ghi đè lên phương thức drawRect của nó.

Như bạn có thể thấy, những gì tôi đã làm là chỉ cần thiết lập một gradient tròn nhưng tôi nạp một ma trận tỉ lệ để nén nó trước khi vẽ nó vào ngữ cảnh. Nếu bạn có kế hoạch làm bất cứ điều gì khác trong phương pháp đó, hãy nhớ rằng bạn có ma trận tại chỗ và mọi thứ bạn làm sẽ bị biến dạng bởi nó.Bạn có thể muốn lưu CTM bằng CGContextSaveGState() trước khi tải ma trận và sau đó khôi phục lại trạng thái ban đầu với CGContextRestoreGState()

Hy vọng đây là những gì bạn đang tìm kiếm.

Chúc mừng.

+0

Ah Tôi quên đề cập đến điều đó, vì trong ví dụ của tôi, tôi đang nghiền nát mọi thứ với chỉ mục 0.1f, điều đó có nghĩa là bạn sẽ nhận được một bóng tối bằng 1/10 chiều cao của khung cảnh. Nếu bạn thiết lập điều này, làm cho tầm nhìn của bạn đủ cao để nhìn thấy bóng tối. Tùy thuộc vào nơi bạn muốn thực sự đặt mã như vậy, bạn sẽ phải đặt một số nhân xung quanh để có bóng hơn tương tự như kích thước xem thực tế. Để đơn giản tôi bỏ qua phần này. –

+0

Bạn cũng sẽ cần phải cắt gradient nếu bạn có kế hoạch vẽ nó xa lề trên như tôi đã làm ở đây. –

+0

Điều này có thể hữu ích, cảm ơn bạn! Tôi sẽ thử điều này khi tôi có thời gian và tôi sẽ liên lạc lại với bạn – NSAddict

1
- (void)viewDidLoad 
{ 
UIImage *natureImage = [UIImage imageNamed:@"nature.jpg"]; 
CALayer *layer = [CALayer layer]; 
layer.bounds = CGRectMake(0, 0, 200, 200); 
layer.position = CGPointMake(380, 200); 
layer.contents = (id)natureImage.CGImage; 

layer.shadowOffset = CGSizeMake(0,2); 
layer.shadowOpacity = 0.70; 
layer.shadowPath = (layer.shadowPath) ? nil : [self bezierPathWithCurvedShadowForRect:layer.bounds].CGPath; 
[self.view.layer addSublayer:layer]; 
} 

- (UIBezierPath*)bezierPathWithCurvedShadowForRect:(CGRect)rect { 

    UIBezierPath *path = [UIBezierPath bezierPath]; 

    CGPoint topLeft  = rect.origin; 
    CGPoint bottomLeft = CGPointMake(0.0, CGRectGetHeight(rect) + offset); 
    CGPoint bottomMiddle = CGPointMake(CGRectGetWidth(rect)/2, CGRectGetHeight(rect) - curve); 
    CGPoint bottomRight = CGPointMake(CGRectGetWidth(rect), CGRectGetHeight(rect) + offset); 
    CGPoint topRight  = CGPointMake(CGRectGetWidth(rect), 0.0); 

    [path moveToPoint:topLeft]; 
    [path addLineToPoint:bottomLeft]; 
    [path addQuadCurveToPoint:bottomRight controlPoint:bottomMiddle]; 
    [path addLineToPoint:topRight]; 
    [path addLineToPoint:topLeft]; 
    [path closePath]; 

    return path; 
} 

Hy vọng điều này sẽ giúp bạn.

+0

Bạn có thấy thẻ 'osx' không? Tôi không nói rằng mã iOS không thể được dịch sang OSX nhưng bạn nên là người làm công việc đó. –