【问题标题】:How to fix the Gradient on text when using an image in swift, as the gradient restarts当渐变重新启动时,如何在快速使用图像时修复文本上的渐变
【发布时间】:2016-04-09 11:26:45
【问题描述】:

我正在尝试在文本上创建渐变,我使用 UIGraphics 来使用渐变图像来创建它。我遇到的问题是渐变正在重新启动。有谁知道我如何缩放渐变以拉伸到文本?

文本位于线框上,将被更改几次。有时它会是完美的,但有时它不是。

渐变应该从黄色变为蓝色,但它会重新启动,见下图:

import UIKit

func colourTextWithGrad(label: UILabel) {
    UIGraphicsBeginImageContext(label.frame.size)
    UIImage(named: "testt.png")?.drawInRect(label.bounds)
    let myGradient: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    label.textColor = UIColor(patternImage: myGradient)

}

【问题讨论】:

    标签: ios swift uilabel core-graphics gradient


    【解决方案1】:

    每次标签大小发生变化时,您都必须重新绘制图像

    这是因为有图案的UIColor 只会被平铺。来自the documentation

    在绘图期间,图案颜色的图像会根据需要平铺以覆盖给定区域。

    因此,当标签的边界发生变化时,您需要自己更改图像大小——因为图案图像不支持拉伸。为此,您可以继承UILabel,并覆盖layoutSubviews 方法。这样的事情应该可以达到预期的效果:

    class GradientLabel: UILabel {
        
        let gradientImage = UIImage(named:"gradient.png")
        
        override func layoutSubviews() {
            
            guard let grad = gradientImage else { // skip re-drawing gradient if it doesn't exist
                return
            }
            
            // redraw your gradient image
            UIGraphicsBeginImageContext(frame.size)
            grad.drawInRect(bounds)
            let myGradient = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            // update text color
            textColor = UIColor(patternImage: myGradient)
        }
    }
    

    虽然值得注意的是,我总是更喜欢自己绘制渐变 - 因为您可以拥有更大的灵活性(假设您想稍后添加另一种颜色)。此外,当您以不同的尺寸重新绘制图像时,图像的质量可能会下降(尽管由于渐变的性质,这应该是相当小的)。

    您可以通过覆盖 UILabel 子类的 drawRect 来相当简单地绘制自己的渐变。例如:

    override func drawRect(rect: CGRect) {
        
        // begin new image context to let the superclass draw the text in (so we can use it as a mask)
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0.0)
        do {
            // get your image context
            let ctx = UIGraphicsGetCurrentContext()
            
            // flip context
            CGContextScaleCTM(ctx, 1, -1)
            CGContextTranslateCTM(ctx, 0, -bounds.size.height)
            
            // get the superclass to draw text
            super.drawRect(rect)
        }
        
        // get image and end context
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        // get drawRect context
        let ctx = UIGraphicsGetCurrentContext()
        
        // clip context to image
        CGContextClipToMask(ctx, bounds, img.CGImage)
        
        // define your colors and locations
        let colors = [UIColor.orangeColor().CGColor, UIColor.redColor().CGColor, UIColor.purpleColor().CGColor, UIColor.blueColor().CGColor]
        let locs:[CGFloat] = [0.0, 0.3, 0.6, 1.0]
        
        // create your gradient
        let grad = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), colors, locs)
        
        // draw gradient
        CGContextDrawLinearGradient(ctx, grad, CGPoint(x: 0, y:bounds.size.height*0.5), CGPoint(x:bounds.size.width, y:bounds.size.height*0.5), CGGradientDrawingOptions(rawValue: 0))
    
    }
    

    输出:


    Swift 4 & 作为子类

    class GradientLabel: UILabel {
        
        // MARK: - Colors to create gradient from
        @IBInspectable open var gradientFrom: UIColor?
        @IBInspectable open var gradientTo: UIColor?
        
        override func draw(_ rect: CGRect) {
            // begin new image context to let the superclass draw the text in (so we can use it as a mask)
            UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0.0)
            do {
                // get your image context
                guard let ctx = UIGraphicsGetCurrentContext() else { super.draw(rect); return }
                // flip context
                ctx.scaleBy(x: 1, y: -1)
                ctx.translateBy(x: 0, y: -bounds.size.height)
                // get the superclass to draw text
                super.draw(rect)
            }
            // get image and end context
            guard let img = UIGraphicsGetImageFromCurrentImageContext(), img.cgImage != nil else { return }
            UIGraphicsEndImageContext()
            // get drawRect context
            guard let ctx = UIGraphicsGetCurrentContext() else { return }
            // clip context to image
            ctx.clip(to: bounds, mask: img.cgImage!)
            // define your colors and locations
            let colors: [CGColor] = [UIColor.orange.cgColor, UIColor.red.cgColor, UIColor.purple.cgColor, UIColor.blue.cgColor]
            let locs: [CGFloat] = [0.0, 0.3, 0.6, 1.0]
            // create your gradient
            guard let grad = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as CFArray, locations: locs) else { return }
            // draw gradient
            ctx.drawLinearGradient(grad, start: CGPoint(x: 0, y: bounds.size.height*0.5), end: CGPoint(x:bounds.size.width, y: bounds.size.height*0.5), options: CGGradientDrawingOptions(rawValue: 0))
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多