快速使用图像时,如何在文本上固定渐变,因为渐变会重新启动 [英] How to fix the Gradient on text when using an image in swift, as the gradient restarts

查看:92
本文介绍了快速使用图像时,如何在文本上固定渐变,因为渐变会重新启动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



文本在线框上,将被更改几次。



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



 导入UIKit 

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

label.textColor = UIColor(patternImage:myGradient)

}


解决方案

每次标签尺寸更改时,您都必须重新绘制图像


这是因为仅对平铺的 UIColor 进行平铺。来自




Swift 4&作为子类


 类GradientLabel:UILabel {

//标记:-用于从
创建渐变的颜色@ IBInspectable打开var梯度来自:UIColor?
@IBInspectable open var gradientTo:UIColor?

覆盖func draw(_ rect:CGRect){
//开始新的图像上下文,让超类在其中绘制文本(因此我们可以将其用作遮罩)
UIGraphicsBeginImageContextWithOptions(bounds.size,false,0.0)
do {
//获取图像上下文
保护ctx = UIGraphicsGetCurrentContext()else {super.draw(rect); return}
//翻转上下文
ctx.scaleBy(x:1,y:-1)
ctx.translateBy(x:0,y:-bounds.size.height)
//获取超类以绘制文本
super.draw(rect)
}
//获取图像和结束上下文
保护img = UIGraphicsGetImageFromCurrentImageContext(),img。 cgImage!= nil else {return}
UIGraphicsEndImageContext()
//获取drawRect上下文
Guard let ctx = UIGraphicsGetCurrentContext()else {return}
//将上下文剪切为图像
ctx.clip(至:边界,蒙版:img.cgImage!)
//定义您的颜色和位置
让颜色:[CGColor] = [UIColor.orange.cgColor,UIColor.red .cgColor,UIColor.purple.cgColor,UIColor.blue.cgColor]
让位置:[CGFloat] = [0.0,0.3,0.6,1.0]
//创建渐变
保护让等级= CGGradient(colorsSpace:CGColorSpaceCreateDeviceRGB(), colors:颜色为CFArray,位置:locs)else {return}
//绘制渐变
ctx.drawLinearGradient(grad,start:CGPoint(x:0,y:bounds.size.height * 0.5) ,结尾:CGPoint(x:bounds.size.width,y:bounds.size.height * 0.5),选项:CGGradientDrawingOptions(rawValue:0))
}
}


I'm trying to create a gradient on text, I have used UIGraphics to use a gradient image to create this. The problem I'm having is that the gradient is restarting. Does anyone know how I can scale the gradient to stretch to the text?

The text is on a wireframe and will be altered a couple of times. Sometimes it will be perfect but other times it is not.

The gradient should go yellow to blue but it restarts see photo below:

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)

}

解决方案

You'll have to redraw the image each time the label size changes

This is because a pattered UIColor is only ever tiled. From the documentation:

During drawing, the image in the pattern color is tiled as necessary to cover the given area.

Therefore, you'll need to change the image size yourself when the bounds of the label changes – as pattern images don't support stretching. To do this, you can subclass UILabel, and override the layoutSubviews method. Something like this should achieve the desired result:

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)
    }
}


Although it's worth noting that I'd always prefer to draw a gradient myself – as you can have much more flexibility (say you want to add another color later). Also the quality of your image might be degraded when you redraw it at different sizes (although due to the nature of gradients, this should be fairly minimal).

You can draw your own gradient fairly simply by overriding the drawRect of your UILabel subclass. For example:

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

}

Output:


Swift 4 & as subclass

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))
    }
}

这篇关于快速使用图像时,如何在文本上固定渐变,因为渐变会重新启动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆