2009-08-20 25 views
22

Tôi biết làm thế nào để vẽ một đường đơn giản:Làm thế nào để vẽ một đường gradient (fading in/out) với Core Graphics/iPhone?

CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); 
CGContextMoveToPoint(context, x, y); 
CGContextAddLineToPoint(context, x2, y2); 
CGContextStrokePath(context); 

Và tôi biết làm thế nào để làm một hình chữ nhật gradient, i.g .:

CGColorSpaceRef myColorspace=CGColorSpaceCreateDeviceRGB(); 
size_t num_locations = 2; 
CGFloat locations[2] = { 1.0, 0.0 }; 
CGFloat components[8] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; 

CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, num_locations); 

CGPoint myStartPoint, myEndPoint; 
myStartPoint.x = 0.0; 
myStartPoint.y = 0.0; 
myEndPoint.x = 0.0; 
myEndPoint.y = 10.0; 
CGContextDrawLinearGradient (context, myGradient, myStartPoint, myEndPoint, 0); 

Nhưng làm thế nào tôi có thể vẽ một đường với một gradient, i.g. mờ dần từ màu đen sang màu trắng (và có thể phai màu đen ở phía bên kia)?

+1

Lưu ý nhanh - câu trả lời hiện được chọn ở đây không chính xác. ** Có thể đột quỵ đường dẫn tùy ý với một gradient ** như [câu trả lời này] (http://stackoverflow.com/a/25034854/2547229) cho thấy. – Benjohn

Trả lời

20

Sau một vài lần thử, giờ đây tôi chắc chắn rằng các độ dốc không ảnh hưởng đến nét vẽ, vì vậy tôi nghĩ rằng không thể vẽ đường kẻ sọc với CGContextStrokePath(). Đối với đường ngang và dọc, giải pháp là sử dụng CGContextAddRect() thay vào đó, may mắn thay là những gì tôi cần. Tôi thay thế

CGContextMoveToPoint(context, x, y); 
CGContextAddLineToPoint(context, x2, y2); 
CGContextStrokePath(context); 

với

CGContextSaveGState(context); 
CGContextAddRect(context, CGRectMake(x, y, width, height)); 
CGContextClip(context); 
CGContextDrawLinearGradient (context, gradient, startPoint, endPoint, 0); 
CGContextRestoreGState(context); 

và tất cả mọi thứ hoạt động tốt. Cảm ơn Brad Larson vì gợi ý quan trọng.

+0

Tôi đã tìm thấy chính xác điều tương tự. Nó sẽ xuất hiện gradient đòi hỏi một đường dẫn clip (hoặc hình chữ nhật) được áp dụng cho bối cảnh đồ họa đầu tiên. Có lẽ điều này là do gradient được hiển thị trong khu vực bao quanh chứ không phải trên đường viền (hoặc hình chữ nhật) của chính nó? – Dalmazio

+0

Điều này không thể hiển thị một đường dốc? – AntiMoron

8

Bạn có thể sử dụng lớp Hoạt ảnh lõi. Bạn có thể sử dụng một CAShaperLayer cho dòng của bạn bằng cách thiết lập thuộc tính đường dẫn của nó và sau đó bạn có thể sử dụng CAGradientLayer làm lớp mặt nạ cho lớp hình dạng của bạn sẽ làm cho đường mờ dần.

Thay thế cuộc gọi CGContext ... của bạn bằng cuộc gọi đến CGPath ... cuộc gọi để tạo đường dẫn đường. Đặt trường đường dẫn trên lớp bằng đường dẫn đó. Sau đó, trong lớp gradient của bạn, chỉ định màu sắc mà bạn muốn sử dụng (có thể là màu đen sang màu trắng) và sau đó đặt mặt nạ là lớp dòng như thế này:

Điều thú vị về lớp gradient là cho phép bạn để chỉ định một danh sách các vị trí nơi gradient sẽ dừng lại, vì vậy bạn có thể mờ dần và mờ dần. Nó chỉ hỗ trợ gradient tuyến tính, nhưng có vẻ như nó có thể phù hợp với nhu cầu của bạn.

Hãy cho tôi biết nếu bạn cần làm rõ.

EDIT: Bây giờ tôi nghĩ về nó, chỉ cần tạo một CAGradientLayer duy nhất là chiều rộng/chiều cao của dòng bạn mong muốn. Chỉ định các màu gradient (đen sang màu trắng hoặc đen để xóa màu) và startPoint và endtPoints và nó sẽ cung cấp cho bạn những gì bạn cần.

+0

Bạn nói đúng, điều này hoàn toàn phù hợp với nhu cầu của tôi, nhưng tiếc là điều này chỉ có sẵn với phiên bản 3 của hệ điều hành iPhone và tôi muốn sử dụng ít nhất 2.2. Dù sao cũng cảm ơn bạn... – Walchy

+1

Tôi đoán bạn có nghĩa là [gradientLayer setMask: LineLayer]; - đúng? Bạn che dấu CAGradientLayer bằng CAShapeLayer. – Palimondo

+0

Rực rỡ. Đã học được rất nhiều điều này. – Ian1971

8

Sau khi bạn vẽ đường, bạn có thể gọi

CGContextClip(context); 

clip tiếp tục vẽ đến khu vực đường của bạn. Nếu bạn vẽ gradient, nó bây giờ sẽ được chứa trong khu vực dòng. Lưu ý rằng bạn sẽ cần phải sử dụng một màu sắc rõ ràng cho dòng của bạn nếu bạn chỉ muốn gradient để hiển thị, và không phải là dòng bên dưới nó.

Có khả năng một đường sẽ quá mỏng để gradient hiển thị, trong trường hợp này bạn có thể sử dụng CGContextAddRect() để xác định khu vực dày hơn.

Tôi trình bày một ví dụ phức tạp hơn về cách sử dụng ngữ cảnh này trong câu trả lời của tôi here.

+1

Tôi đã thử đề xuất của bạn: \t CGContextSetLineWidth (ngữ cảnh, 10,0); // phải đủ dày \t CGContextSetRGBStrokeColor (ngữ cảnh, 0,0, 0,0, 0,0, 0,0); \t CGContextMoveToPoint (ngữ cảnh, 50,50); \t CGContextAddLineToPoint (ngữ cảnh, 100,100); \t CGContextStrokePath (ngữ cảnh); \t CGContextClip (ngữ cảnh); \t CGContextDrawLinearGradient (ngữ cảnh, myGradient, myStartPoint, myEndPoint, 0); nhưng điều này ném : doClip: đường dẫn trống. Tài liệu nói rằng CGContextStrokePath (ngữ cảnh); xóa đường dẫn - không có phương pháp này, không có lỗi nào được ném, nhưng không có gì được vẽ cả. Bất kỳ ý tưởng nào? – Walchy

0
CGContextMoveToPoint(context, frame.size.width-200, frame.origin.y+10); 
CGContextAddLineToPoint(context, frame.size.width-200, 100-10); 
CGFloat colors[16] = { 0,0, 0, 0, 
    0, 0, 0, .8, 
    0, 0, 0, .8, 
    0, 0,0 ,0 }; 
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB(); 
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 4); 

CGContextSaveGState(context); 
CGContextAddRect(context, CGRectMake(frame.size.width-200,10, 1, 80)); 
CGContextClip(context); 
CGContextDrawLinearGradient (context, gradient, CGPointMake(frame.size.width-200, 10), CGPointMake(frame.size.width-200,80), 0); 
CGContextRestoreGState(context); 

công việc của mình cho tôi.

25

Có thể đột quỵ đường dẫn tùy ý với độ dốc hoặc bất kỳ hiệu ứng tô màu nào khác, chẳng hạn như mẫu.

Như bạn đã tìm thấy, đường dẫn vuốt ve không được hiển thị với độ dốc hiện tại. Chỉ các đường dẫn đầy mới sử dụng gradient (khi bạn chuyển chúng thành một clip và sau đó vẽ gradient).

Tuy nhiên, Core Graphics có một thủ tục ngạc nhiên mát mẻ CGContextReplacePathWithStrokedPath rằng sẽ làm thay đổi đường dẫn mà bạn có ý định đột quỵ vào một con đường mà là tương đương khi điền.

Phía sau hậu trường, CGContextReplacePathWithStrokedPath xây dựng một đa giác cạnh xung quanh đường dẫn đột quỵ và công tắc cho đường dẫn bạn đã xác định. Tôi dự đoán rằng công cụ dựng hình đồ họa lõi có thể thực hiện điều này dù sao trong các cuộc gọi đến CGContextStrokePath.

Dưới đây là tài liệu hướng dẫn của Apple về vấn đề này:

thạch anh tạo ra một con đường vuốt sử dụng các thông số của bối cảnh đồ họa hiện nay. Đường dẫn mới được tạo để điền nó vẽ cùng một pixel như vuốt đường dẫn ban đầu. Bạn có thể sử dụng đường dẫn này giống như cách bạn sử dụng đường dẫn của bất kỳ ngữ cảnh nào. Ví dụ, bạn có thể clip vào phiên bản vuốt ve của một đường dẫn bằng cách gọi hàm này theo sau là một cuộc gọi đến hàm CGContextClip.

Vì vậy, chuyển đổi đường dẫn của bạn trong một cái gì đó bạn có thể điền, rẽ mà vào một clip, và sau đó vẽ gradient của bạn. Hiệu ứng sẽ như thể bạn đã vuốt ve đường dẫn với gradient.

Nó sẽ giống như thế này ...

// Get the current graphics context. 
    // 
    const CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Define your stroked path. 
    // 
    // You can set up **anything** you like here. 
    // 
    CGContextAddRect(context, yourRectToStrokeWithAGradient); 

    // Set up any stroking parameters like line. 
    // 
    // I'm setting width. You could also set up a dashed stroke 
    // pattern, or whatever you like. 
    // 
    CGContextSetLineWidth(context, 1); 

    // Use the magical call. 
    // 
    // It turns your _stroked_ path in to a **fillable** one. 
    // 
    CGContextReplacePathWithStrokedPath(context); 

    // Use the current _fillable_ path in to define a clipping region. 
    // 
    CGContextClip(context); 

    // Draw the gradient. 
    // 
    // The gradient will be clipped to your original path. 
    // You could use other fill effects like patterns here. 
    // 
    CGContextDrawLinearGradient(
     context, 
     yourGradient, 
     gradientTop, 
     gradientBottom, 
     0 
    ); 

Tiếp tục ghi chú

Đó là giá trị nhấn mạnh một phần của tài liệu trên:

thạch anh tạo ra một con đường vuốt ve sử dụng các thông số ngữ cảnh đồ họa hiện tại.

Thông số hiển thị là chiều rộng đường kẻ. Tuy nhiên, tất cả trạng thái bản vẽ dòng được sử dụng, chẳng hạn như mẫu nét vẽ, giới hạn bộ giới hạn, kết nối đường thẳng, mũ, mẫu dấu gạch ngang, v.v. Điều này làm cho phương pháp tiếp cận cực kỳ mạnh mẽ.

Để biết thêm chi tiết, hãy xem this answer trong số this S.O. question.

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