2013-09-20 2 views
0

Может ли кто-нибудь помочь мне в рисовании одного определенного градиента с помощью CoreGraphics? Просто дать подсказку было бы достаточно. Пример кода, который вызывает глубочайшее уважение. мне нужна эта форма:Градиент прямоугольника CoreGraphics

enter image description here

Я попытался следующий код:

-(UIImage *)imageWithGradientBorder 
{ 
    CGRect rect=CGRectMake(0, 0, self.size.width, self.size.height); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 
    CGContextRef ctx= CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, 8, rect.size.width, colorSpace, kCGImageAlphaNone); 
    CGGradientRef glossGradient; 
    size_t num_locations = 4; 
    CGFloat locations[4] = { 0.0, 0.1, 0.9, 1.0 }; 
    CGFloat components[16] = { 0, 0, 0, 1, 1.0, 1.0, 1.0, 1, 1.0, 1.0, 1.0, 1, 0, 0, 0, 1}; 
    glossGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, num_locations); 
    CGRect currentBounds = rect; 

    CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f); 
    CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMaxY(currentBounds)); 
    topCenter = CGPointMake(0.0f, CGRectGetMidY(currentBounds)); 
    midCenter = CGPointMake(CGRectGetMaxX(currentBounds), CGRectGetMidY(currentBounds)); 

    CGContextDrawLinearGradient(ctx, glossGradient, topCenter, midCenter, 0); 
    CGImageRef mask = CGBitmapContextCreateImage(ctx); 
    CGContextRelease(ctx); 
    CGImageRef maskedImageRef = CGImageCreateWithMask([self CGImage], mask); 
    CGImageRelease(mask); 
    UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef]; 
    CGImageRelease(maskedImageRef); 
    return maskedImage; 
} 

но рисует градиент только с левой стороны.

+0

Какой код вы пробовали до сих пор, и что же он сделал не так? – Wain

+0

продлил вопрос – heximal

+0

Вы пробовали вращать контекст и снова рисовать для других сторон? – sleepwalkerfx

ответ

1
topCenter = CGPointMake(0.0f, CGRectGetMidY(currentBounds)); 
midCenter = CGPointMake(CGRectGetMaxX(currentBounds), CGRectGetMidY(currentBounds)); 

Этих 2 переменных имеют вводящее в заблуждении названия, они не являются на самом деле центром верхнего и среднего центра, они в середине левые и правая середины. Поэтому когда вы позвоните:

CGContextDrawLinearGradient(ctx, glossGradient, topCenter, midCenter, 0); 

Вы рисуете градиент слева направо.

Что нужно сделать, чтобы организовать ваши точки и нарисовать градиент 4 раза (L-> R, R-> L, T-> B, B-> T). В зависимости от того, как вы хотите, чтобы углы выглядели точно, вам может понадобиться сделать маскировку между каждым градиентным рисунком, чтобы предотвратить градиент от рисования до конца.

+0

Разве он не сделает нежелательные артефакты в углах из-за перекрытия градиентов? Я пытаюсь достичь стыковки градиентов вдоль диагоналей прямоугольника (например, на рисунке выше). – heximal

+0

Вот почему я сказал, что вам может понадобиться замаскировать. Посмотрите на установочные обтравочные контуры, используйте треугольники от угловых точек до центра. – Wain

0

ОК, я создал одно обходное решение.

CGContextRef currentContext = UIGraphicsGetCurrentContext(); 
CGContextRef context = currentContext; 
CGContextSaveGState(currentContext); 
CGFloat colStep = 255/borderWidth/10; 
colStep = colStep/255; 
for (int i = 0; i < floor(borderWidth * 10); i++) { 
    CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:colStep*i alpha:1].CGColor); 
    CGFloat delta = i/10; 
    CGRect rectToDraw = CGRectMake(delta,delta,rect.size.width - delta * 2,rect.size.height - delta * 2); 
    CGContextFillRect(context, rectToDraw); 
} 


CGContextRestoreGState(currentContext); 
0

Другие ответы лучше первоначального вопроса, но если вам не нужно рисовать CoreGraphics, вы можете рассмотреть нарезку изображения с каталогом активов. Вы можете создать градиент и углы в графической программе и сделать его изменяемым по размеру в Xcode. https://developer.apple.com/library/ios/recipes/xcode_help-image_catalog-1.0/chapters/SlicinganImage.html

0
class BorderView: UIView { 
    private var lineHeight: CGFloat = 80 
    var colors: [UIColor] = [UIColor.black, UIColor.white] 
    { 
     didSet { 
      setNeedsDisplay() 
     } 
    } 
    override func draw(_ rect: CGRect) { 

     let line1 = _getLineLayer() 
    layer.addSublayer(line1) 

     let line2 = _getLineLayer() 
    let t = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -rect.maxY + lineHeight) 
     line2.setAffineTransform(t) 
     layer.addSublayer(line2) 

     let line3 = _getLineLayer() 
     let t1 = CGAffineTransform(rotationAngle:  CGFloat(M_PI_2)).translatedBy(x: rect.midX - lineHeight/2, y: -rect.midY + lineHeight/2) 
     line3.setAffineTransform(t1) 
     layer.addSublayer(line3) 

     let line4 = _getLineLayer() 
     let t2 = CGAffineTransform(rotationAngle: -(CGFloat)(M_PI_2)).translatedBy(x: -rect.midX + lineHeight/2, y: -rect.midY + lineHeight/2) 
     line4.setAffineTransform(t2) 
     layer.addSublayer(line4) 


    } 

    private func _getLineLayer() -> CALayer { 

     let gl = CAGradientLayer() 
     gl.frame = CGRect(x: 0, y: 0, width: layer.bounds.width, height: lineHeight) 
     gl.colors = colors.map({$0.cgColor}) 

     // Get mask layer 
     let p1 = CGPoint.zero 
     let p2 = CGPoint(x: layer.bounds.width, y: 0) 
     let p3 = CGPoint(x: layer.bounds.width - lineHeight, y: lineHeight) 
     let p4 = CGPoint(x: lineHeight, y: lineHeight) 

     let path = UIBezierPath() 
     path.move(to: p1) 
     path.addLine(to: p2) 
     path.addLine(to: p3) 
     path.addLine(to: p4) 
     path.close() 
     let shapeLayer = CAShapeLayer() 
     shapeLayer.frame = gl.frame 
     shapeLayer.path = path.cgPath 
     gl.mask = shapeLayer 
     return gl 
    } 
} 

Использование

let frame = CGRect(x: 0, y: 0, width: 500, height: 500) 
let view = BorderView(frame: frame) 
view.backgroundColor = .white 
PlaygroundPage.current.liveView = view 
view.colors = [.black, .white] 

Output view

Смежные вопросы