作者:霖溦
原文链接:http://www.jianshu.com/p/93592bdc99c6

前言

文字渐变是一种填充效果,就像KTV的歌词显示那样,可以做到单个文字颜色的渐变。关于这一效果的实现,想到了两种思路,一种是让字体镂空,改变背景色,另一种就是参考实现歌词进度那样的显示效果。先看一下Demo中关于将要介绍的几种实现的整体效果:

Demo详见GitHub:JXTMarkLabel

1. 镂空文字 - JXTHollowOutLabel

如果说上面的Demo效果还不够直观的话,看这里的图层关系:

镂空文字效果的实现基于drawRect重绘,具体参考了两篇帖子:

1.Drawing a path with subtracted text using Core Graphics

2.drawRect drawing 'transparent' text?

想了解原理的可以参考原文,根据帖子中提供的代码,我这里稍作了简化和封装,也就是工程里的JXTHollowOutLabel类。效果实现的核心代码如下:

- (void)drawSubtractedText:(NSString *)text inRect:(CGRect)rect inContext:(CGContextRef)context
{
//将当前图形状态推入堆栈
CGContextSaveGState(context);
//设置混合色
CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
//label上面添加label
UILabel *label = [[UILabel alloc] initWithFrame:rect];
label.font = _font;
label.text = text;
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = _backgroundColor;
[label.layer drawInContext:context];
//把堆栈顶部的状态弹出,返回到之前的图形状态
CGContextRestoreGState(context);
}

该类的调用同系统的UILabel类似(该类是其子类),不过因为封装的问题,初始化仅支持initWithFrame一种,也就是不支持xib。再回到文章最开始的话题,因为有了镂空文字,这个问

题就很简单了,只需要在这个label的底层添加一个可滑动的颜色块,渐变效果也就有了,效果如下:

如果看得足够仔细,可以发现有几个title之间存在很细的裂隙,那是因为我这里的标题的label尺寸是根据文字长短动态计算的,用了boundingRectWithSize方法,实际发现,一旦title的内容是中文和数字或字母混合的,例如图中的“b站”,就会产生计算误差,虽然很小。。。这种镂空字实现的缺憾之一就是没能支持毛玻璃效果,如果能支持的话,那么背景的滑块的颜色就可以透过来,镂空的质感会更好。

2. 基于CoreAnimation的KTV歌词视图

这部分只是简单提一下,因为我并不是用这种高大上的方法实现最前面的那个歌词进度的效果的。

歌词的进度显示是个比较复杂的问题,除了刷新效率,还有就是刷新速度的动态变化的问题,以及换行刷新。

3.歌词进度显示 - JXTProgressLabel

因为没有像歌词进度显示那样有那么多顾虑,我这里使用了一种比较白痴的方法,这个方法原来是星级评价那里使用的,星级评价就是满5星,根据数据动态展示几点几星的那个问题,有的人是直接几星贴几张图,半星就是半颗星的图,但实际上用两层view再加一层控制的view,一共三层,叠加起来,就很容易实现这个效果:

上图中:底层是白色字体的那个label,也就是backgroundLabel,中间层,也就是现在标示的蓝色的透明view,是clipView,最上层橙色文字的label,是foregroundLabel。三者的层级关系如下:

[self addSubview:self.backgroundLabel];
[self.clipView addSubview:self.foregroundLabel];
[self addSubview:self.clipView];

foregroundLabel是clipView的子视图,_clipView.clipsToBounds = YES需要设置,此时控制clipView的宽度,也就控制了foregroundLabel的文字显示的进度(label的显示宽度),backgroundLabel和clipView是并列关系,后者在前者图层的上层,也就展现了背景label随着中间层clipView的动态宽度变化,从而动态渲染颜色的视觉假象。星级控制也是同样的原理。

JXTProgressLabel的使用也同系统的UIlabel类似,初始化也仅支持initWithFrame一种,初始化时还需要设置前景和背景label的颜色:

_progressLabel.backgroundTextColor = [UIColor whiteColor];
_progressLabel.foregroundTextColor = [UIColor orangeColor];

控制显示进度时,支持两种方法,一种是直接控制clipView的宽度,也就是_progressLabel.clipWidth,但这种方式比较局限,推荐直接控制_progressLabel2.dispProgress,dispProgress是0-1之间的小数。

JXTProgressLabel除了可以作为类似的歌词进度显示,还可以做进度指示器,具体用法看具体需求了。

4. 歌词进度显示的升级 - JXTSlideClipLabel

还是回到最开始的问题,如果直接使用之前提到的JXTProgressLabel,很明显是不能直接满足需求的,因为title的颜色是变过之后,又要变回的,所以,上面的JXTProgressLabel的clipView的宽度应该是限定的或者说应该是随着title长短动态改变的,而不是一直增大的。

如果只是限制clipView的宽度,位置水平移动,很明显,其子视图foregroundLabel也会跟着移动,那么之前动态渲染的假象也就不复存在了,这里解决的方法也比较取巧:foregroundLabel的frame同backgroundLabel一样,但是其坐标随着固定宽度的clipView的移动,反方向退行,三者之间的图层关系还是不变的。

具体的效果就是最开始的那个展示。

JXTSlideClipLabel在Demo中只是原理的封装,没有考虑具体情境而普适,demo中是根据title数量,动态创建了label,其实只使用一个label应该也是可以的,只要保证三者的图层关系就好。只是用一个label做foregroundLabel或backgroundLabel的话,标题组应该拼接起来成一个字符串,具体没有试,应该是行得通的。

5. 一种类似视差效果的视图 - ParallaxView

这个的实现原理和JXTSlideClipLabel一样,可以移动的view中贴了一张大图,但限于clipView尺寸,只能显示一部分,这一部分根据移动的坐标,也动态“退行”,就成了这个效果,好像一块“透视镜”,比较有意思,那个圆形的本来是想试着做成一个放大镜的,但是方法后的视图的坐标变换没有处理好,暂时放弃了……ParallaxView的代码同样只是演示,滑动视图的边界没有限定,可以自行处理。

以上就是造轮子过程中遇到的几个比较有意思的问题了,总归就是特种的label,使用情境可能比较局限,但是实现思路还是比较有意思的。

参考文章:

  1. iOS UILabel镂空特效

  2. Drawing a path with subtracted text using Core Graphics

  3. drawRect drawing 'transparent' text?

  4. RSMaskedLabel

  5. iOS歌词逐渐变色动画

  6. 基于Core Animation的KTV歌词视图的平滑实现

iOS 特种label:镂空文字、类歌词进度显示文字相关推荐

  1. 镂空文字、类歌词进度显示文字

    Demo详见GitHub:JXTMarkLabel 镂空文字 - JXTHollowOutLabel 镂空文字效果的实现基于drawRect重绘,具体参考了两篇帖子: Drawing a path w ...

  2. 文字根据图片环绕 + 显示文字两行后省略号

    首先看布局: "拼团价" 这里是图片,标题文字要环绕,第二行文字要在图片的下面 1.正常的做法是:设置图片float,这样就可以实现: .info-content_title{cl ...

  3. opengl学习之显示文字

    本课我们来谈谈如何显示文字. OpenGL并没有直接提供显示文字的功能,并且,OpenGL也没有自带专门的字库.因此,要显示文字,就必须依赖操作系统所提供的功能了. 各种流行的图形操作系统,例如Win ...

  4. 点击按钮显示文字,再次点击隐藏文字

    点击按钮显示文字,再次点击隐藏文字 点击按钮显示文字,再次点击按钮隐藏文字 通过if条件判断css样式来做 <!DOCTYPE html> <html lang="en&q ...

  5. OpenGL显示文字--显示英文

    本文转自:http://blog.sina.com.cn/s/blog_4ff085000100devp.html OpenGL并没有直接提供显示文字的功能,并且,OpenGL也没有自带专门的字库.因 ...

  6. 转载:OpenGL显示文字

    转载:OpenGL显示文字 2010年07月03日 本课我们来谈谈如何显示文字. OpenGL并没有直接提供显示文字的功能,并且,OpenGL也没有自带专门的字库.因此,要显示文字,就必须依赖操作系统 ...

  7. IOS label设置多行显示并且文字在最上方显示

    var customLabel = new UILabel (new RectangleF(10,10,300,30)); customLabel.Text ="Display this t ...

  8. IOS之Label画一条删除线

    IOS之Label画一条删除线 例如上面的价格100 如何对100添加删除线. 我们需要自定义一个Label,继承于UILabel系统类.在xib上对控件添加自定义Label类.LJCenterLab ...

  9. 一劳永逸,iOS 网页视图控制器通用类封装

    原文链接:http://www.jianshu.com/p/553424763585 随着 H5 的发展,在 iOS 开发中,网页视图的使用率逐渐提升,为了增加代码封装度.减轻开发负担,因此通常会对网 ...

最新文章

  1. wangEditor 上传图片,回调函数 Cannot read properties of undefined
  2. python3 str() repr() 区别
  3. UA MATH523A 实分析3 积分理论例题 判断函数可积性的一个题目
  4. 以持续集成工具实现DevOps之禅
  5. controller如何保证当前只有一个线程执行_聊聊Spring线程安全,读完之后,大部分程序员收藏了......
  6. wxPython做界面的适用性
  7. (2021) 25 [持久化] 文件系统实现:FAT和UNIX文件系统
  8. 新版ubuntu中打开终端的方法和安装ssh 的方法
  9. 蓝牙遥控开关c语言程序,单片机蓝牙控制开关制作(程序源码+安卓APP分享)
  10. 希捷四十载:如何做好一家非常规存储公司?
  11. IDEA自动编译不用每次make
  12. python oop 继承_关于oop:使类数据在python中可继承的正确方法是什么?
  13. 一次搭建Spark集群(standalone、yarn、高可用)
  14. linux缺页异常处理--内核空间
  15. 申请数据库资源池的三种方式(Map,properties)
  16. Iptables实现 DMZ 区域的服务器简单的发布策略
  17. 玛雅历 —— C++
  18. 【2023】DevOps、SRE、运维开发面试宝典之Redis相关面试题
  19. 欧洲急了,正式发起 2nm 芯片总攻
  20. 【windows——高效工作】写作篇

热门文章

  1. 外校保研北大计算机,北大2018年本校保研率超53% 外校生多来自双一流名校
  2. 黑帽技术联盟:黑帽SEO与白帽SEO之争
  3. 无线路由器dhcp服务器怎么设置,磊科NW705P无线路由器上DHCP服务器设置操作步骤...
  4. 原生JavaScript实现日志搜索高亮的解决方案
  5. Java 多态实际操练--使用多态的特征创建不同宠物的玩耍方法
  6. win10 安装 Linux子系统(WSL)
  7. Connection must be valid and open.
  8. 液晶的介电各向异性、双折射特性和电控双折射特性
  9. 降低包装成本的 13 种简单方法
  10. 按键精灵---插件之后台发送字符串