开发中有时候会遇到这样的需求,要给用户一个取色板,让用户从中自由地选取颜色,用来改变主题或者控制灯具的颜色等。这时候我们就需要获取一个视图的指定坐标的颜色值。
使用场景
有时候我们可能会需要一个取色器,例如我的蓝牙灯项目,让用户从一个取色器中随意取色:
那么如何从一个图片中取色呢? Stack Overflow 已经有大神给出了核心代码,这段代码是对 UIImage
的扩展,使用起来还不是很方便。于是我根据需求确定了接口:
/** |
调用起来应该是这样的:
// 已知imageView、point |
因为取色板一般是圆形的,如果坐标点超出了圆形但依然在imageView的frame内,可能会返回一些用户不期望的结果,用block巧妙地解决了这一问题,超出范围就不再有回调。如果你认为我的封装使用起来更加方便,可以继续阅读下面详细内容。
开始使用
推荐CocoaPods方式,在podfile中添加一行:
pod 'AXKit' |
然后在终端中执行 pod install
即可完成安装。
AXKit的全局头文件是:
// 通过CocoaPods或静态库方式安装 |
接口声明
从指定点获取RGBA值
- (void)ax_getRed:(nullable CGFloat *)red green:(nullable CGFloat *)green blue:(nullable CGFloat *)blue alpha:(nullable CGFloat *)alpha withPoint:(CGPoint)point; |
需要自己创建变量,然后把地址传进去,然后才能用,不推荐直接使用。
从指定点获取RGBA值,并在block中执行操作
加了一个block,调用起来就方便许多:
- (void)ax_getRGBAWithPoint:(CGPoint)point completion:(void(^)(CGFloat red,CGFloat green,CGFloat blue,CGFloat alpha))completion; |
优点是不需要自己创建变量,直接调用方法,在block回调里直接获得red/green/blue/alpha值。
但是,很多时候,我们用的取色器是圆形的,就需要再进行一点封装。
从圆形范围内的指定点获取RGBA值,并在block中执行操作
- (void)ax_getRGBAFromCircleWithPoint:(CGPoint)point completion:(void (^)(CGFloat red,CGFloat green,CGFloat blue,CGFloat alpha))completion; |
跟第2种调用方法一模一样,但是区别是超出圆形范围之后就不再执行block回调了,这是一种安全的做法。如果不用block方式,那么即使超出了圆形范围,也一定会返回对应的rgba值,会造成不想要的后果。
block的回调机制巧妙地解决了这个问题。
如果我想直接获得一个UIColor对象呢,跟获取RGBA一样有三种方法。
从指定点获取UIColor对象
- (nullable UIColor *)ax_getColorWithPoint:(CGPoint)point; |
由声明可以看出来,返回的值是一个可空类型,因此这跟第一种方法一样是不安全的。
从指定点获取UIColor对象,并在block中执行操作
- (void)ax_getColorWithPoint:(CGPoint)point completion:(void(^)(UIColor *color))completion; |
这种方法比第4种要方便一些,如果超出UIImageView的时候就不执行block里的代码。
从圆形范围内的指定点获取UIColor对象,并在block中执行操作
- (void)ax_getColorFromCircleWithPoint:(CGPoint)point completion:(void (^)(UIColor *color))completion; |
引言中的Demo用的就是这一种方法,在圆形取色器中取色,既方便又安全。
相关资料:
Simple way to read pixel color values from an PNG image on the iPhone?