ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Quartz 2D实现文字镂空效果

2022-01-12 18:03:50  阅读:207  来源: 互联网

标签:文字 蒙版 Quartz ctx 2D backgroundColor 上下文 绘制 镂空


什么是镂空效果,下图就是一个镂空效果的文字:

从图可知,文字是透明的,可以看到下面的图片内容,而UILabel其它部分是白色背景。

使用Quartz 2D绘制镂空效果,大体思路如下:

  1. 实现一个UILabel的子类(这个不是必须的,这样做的目的是为了利用UILabel自身的文字绘制功能方便的绘制出文字,你也可以采用CoreText绘制文字)
  2. 初始化当前视图时确保backgroundColor==.clear(这样做是实现落空文字的关键,因为文字部分必须是透明的)
  3. 利用UILabel自身的绘制方法,绘制出一个文字蒙版(注意:绘制的原图必须是透明底,白色文字(确保textColor为.white)。这样才能正确的创建一个我们需要的文字蒙版)
  4. 调用clip(to rect: CGRect, mask: CGImage)来裁剪当前视图的上下文,mask就是3中创建的蒙版(在此之前需要转换上下文的坐标系)
  5. 填充上下文背景色

附上代码:

class PiercedLabel: UILabel {
    
    override var textColor: UIColor!{
        didSet {
            if textColor != .white {
                textColor = .white // 要实现一个镂空的文字,这里的颜色必须设置成白色
            }
        }
    }
    
    override var backgroundColor: UIColor?{
        didSet {
            // backgroundColor要确保始终为.clear(透明色),这样才可以实现一个镂空效果
            guard let color = backgroundColor else {
                backgroundColor = .clear
                // 当设置backgroundColor == nil时,我们默认背景为白色
                bgColor = .white
                return
            }
            if color != .clear {
                bgColor = color // 保留设置的背景色,以便后续绘制背景
                backgroundColor = .clear
            }
        }
    }
    
    // 用于绘制背景色
    private var bgColor: UIColor!
    
    init() {
        super.init(frame: .zero)
        config()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        config()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        config()
    }
    
    private func config(){
        textColor = .white
        bgColor = .white
        backgroundColor = .clear
    }
    
    override func draw(_ rect: CGRect) {
        
        // 创建一个用于绘制图片的图形上下文,这里必须是透明的,以便创建一个文字蒙版
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        guard let maskContext = UIGraphicsGetCurrentContext() else {
            return
        }
        // 注意:此时的maskContext并不是当前draw方法提供的上下文,而是我们调用UIGraphicsBeginImageContextWithOptions
        //      构建的新的图形上下文,我们在这个上下文中绘制文字蒙版
        // 绘制文字到maskContext上下文中
        super.draw(rect)
        // 获取maskContext上下文的bitmap图片
        guard let textImg = maskContext.makeImage() else {
            UIGraphicsEndImageContext() // 结束maskContext上下文
            return
        }
        UIGraphicsEndImageContext() // 结束maskContext上下文
        // 注意:此时的textImg并不能作为文字蒙版,我们需要通过如下方法创建一个蒙版图片
        // 创建蒙版图
        guard let maskImg = CGImage(maskWidth: textImg.width,
                                    height: textImg.height,
                                    bitsPerComponent: textImg.bitsPerComponent,
                                    bitsPerPixel: textImg.bitsPerPixel,
                                    bytesPerRow: textImg.bytesPerRow,
                                    provider: textImg.dataProvider!,
                                    decode: textImg.decode,
                                    shouldInterpolate: textImg.shouldInterpolate) else {
            return
        }
        
        // 获取当前draw方法提供的上下文,我们需要将内容绘制到这里
        guard let ctx = UIGraphicsGetCurrentContext() else {
            return
        }
        // 先保存当前上下文状态
        ctx.saveGState()
        ctx.clear(rect)
        // 调整当前上下文的坐标系,因为ctx.draw绘制的坐标系是按照左下角问原点的
        // 因此我们需要将坐标系改成左上角,这样绘制的结果才是正确的,否则文字是颠倒的
        ctx.translateBy(x: 0, y: rect.height)
        ctx.scaleBy(x: 1, y: -1)
        
        // 使用蒙版进行裁剪,它会将ctx上下文rect区域的文字部分裁减掉
        ctx.clip(to: rect, mask: maskImg)
        
        // 绘制背景色(注意:被裁减掉的部分不会填充,这样就形成了一个镂空的效果了)
        // 因为ctx上下文是根据当前视图的backgroundColor创建的,而backgroundColor == .clear,是一个透明的
        // 所以ctx就是一个含有透明层的上下文,被裁剪掉的文字部分就是一个透明的了
        // 这也是为什么要确保backgroundColor == .clear了
        bgColor.setFill()
        ctx.fill(rect)
    }
}

代码中的注释已经写的很详细了,具体的解释就不详细描述了

下面是绘制原文本和蒙版的对照图:

原文本:是一个透明底,白色文字

蒙版:是一个透明底,黑色文字

有人会想到,那我们可不可以直接用原文本图片作为蒙版呢?可以,但是那将不是我们想要的效果,它将会是下面的效果:

背景色成为了文字的颜色,而背景色却成为了透明的。这正与我们想要的效果相反。

因此我们必须通过CGImageMaskCreate创建一个蒙版图片。

关于ImageMask的解释可以查看苹果官方文档

截取部分说明:

Image masks must be 1, 2, 4, or 8 bits per component. For a 1-bit mask, a sample value of 1 specifies sections of the mask that are masked out; these sections block the current fill color. A sample value of 0 specifies sections of the mask that are not masked out; these sections show the current fill color of the graphics state when the mask is painted. You can think of the sample values as an inverse alpha. That is, a value of 1 is transparent and 0 is opaque.

 

标签:文字,蒙版,Quartz,ctx,2D,backgroundColor,上下文,绘制,镂空
来源: https://www.cnblogs.com/zbblog/p/15793395.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有