iOS 引导图的聚光灯效果代码实现

  1. 应用背景
    一般一个app进入一个新的页面,或者有新的功能更新的时候都会有一个新手引导来帮助用户快速了解新功能。而这个引导图一般针对某个功能都有聚光灯效果。
  2. 实现方案介绍
    其中背景色在指定的地方有聚光灯的效果。实现方案一般有两种:UI设计给出的一张半透明的图片作为背景图片来实现的;用代码的方式加载一张半透明具有聚光灯效果的背景图片。
  3. 实现方案思路
    新建一个UIView的子类(SpotlightView),然后重写SpotlightView的drawRect:方法,将这个渐变背景色画在view上。在外边使用该view,只需要指定聚光灯的位置,和聚光灯的大小。
  4. 方案的代码实现
 - (void)drawRect:(CGRect)rect {
    //获取上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    //在上下文中创建一个背景图
    CGImageRef backgroundImage = CGBitmapContextCreateImage(context);
    //将当前context压入堆栈,保存现在的context状态
    CGContextSaveGState(context);
    //翻转上下文
    CGContextTranslateCTM(context, 0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    // 创建色彩空间对象
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();

    // 创建起点颜色分量的数组
    CGFloat white[4] = {1.0,1.0,1.0,1.0};
    // 创建终点颜色分量的数组
    CGFloat black[4] = {0.0,0.0,0.0,0.8};
    CGFloat components[8] = {
        white[0],white[1],white[2],white[3],
        black[0],black[1],black[2],black[3],
    };
    // 起点和终点颜色位置
    CGFloat colorLocations[2] = {0.25,0.5};
    //创建渐变梯度CGGradientRef
    CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorspace, components, colorLocations, 2);
    //创建一个径向渐变
    CGContextDrawRadialGradient(context, gradientRef, _position, 0.0f, _position, _radius * 5, 0);
    //释放渐变对象
    CGGradientRelease(gradientRef);
    //恢复到之前的context
    CGContextRestoreGState(context);

    //画背景图
    CGImageRef maskImage = CGBitmapContextCreateImage(context);
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskImage),
                                        CGImageGetHeight(maskImage),
                                        CGImageGetBitsPerComponent(maskImage),
                                        CGImageGetBitsPerPixel(maskImage),
                                        CGImageGetBytesPerRow(maskImage),
                                        CGImageGetDataProvider(maskImage),
                                        NULL,
                                        FALSE);
    CGImageRef masked = CGImageCreateWithMask(backgroundImage, mask);
    CGImageRelease(backgroundImage);
    CGContextClearRect(context, rect);
    CGContextDrawImage(context, rect, masked);
    CGImageRelease(maskImage);
    CGImageRelease(mask);
    CGImageRelease(masked);
}

我们可以使用CGGradientRef来创建轴向(axial)或径向(radial)渐变。一个渐变是从一个颜色到另外一种颜色的填充。
一个轴向渐变(也称为线性渐变)沿着由两个端点连接的轴线渐变。所有位于垂直于轴线的某条线上的点都具有相同的颜色值。
一个径向渐变也是沿着两个端点连接的轴线渐变,不过路径通常由两个圆来定义。
上述代码创建了一个径向渐变。
5. 主要函数介绍

这里主要用到了CGContextDrawRadialGradient和CGGradientCreateWithColorComponents函数。

void CGContextDrawRadialGradient( 
CGContextRef context,   //绘制图形的上下文
CGGradientRef gradient, //一个渐变梯度CGGradientRef
CGPoint startCenter,    // 颜色渐变起点的中心点
CGFloat startRadius,    // 起点的半径 
CGPoint endCenter,      // 颜色渐变终点的中心点
CGFloat endRadius,      //终点的半径
CGGradientDrawingOptions options //当你的起点或者终点不在图形上下文的边缘内时,指定该如何处理。你可以使用你的开始或结束颜色来填充渐变以外的空间。此参数为以下值之一:KCGGradientDrawsAfterEndLocation扩展整个渐变到渐变的终点之后的所有点 KCGGradientDrawsBeforeStartLocation扩展整个渐变到渐变的起点之前的所有点。0不扩展该渐变。
);

对于渐变梯度CGGradientRef的创建我们可以使用CGGradientCreateWithColorComponents函数

CGGradientCreateWithColorComponents (
   CGColorSpaceRef space,//色彩空间
   const CGFloat *components,//颜色分量的数组
   const CGFloat *locations,//位置数组
   size_t count//位置的数量
);

1)色彩空间:(Color Space)这是一个色彩范围的容器,类型必须是CGColorSpaceRef.对于这个参数,我们可以传入CGColorSpaceCreateDeviceRGB函数的返回值,它将给我们一个RGB色彩空间。
2)颜色分量的数组:这个数组必须包含CGFloat类型的红、绿、蓝和alpha值。数组中元素的数量和接下来两个参数密切。从本质来讲,你必须让这个数组包含足够的值,用来指定第四个参数中位置的数量。所以如果你需要两个位置(起点和终点),那么你必须为数组提供两种颜色。
3) 位置数组:颜色数组中各个颜色的位置。此参数控制该渐变从一种颜色过渡到另一种颜色的速度有多快。
4)位置的数量:这个参数指明了我们需要多少颜色和位置。

6 . 运行效果图展示
添加聚光灯效果前
iOS 引导图的聚光灯效果代码实现_第1张图片
添加聚光灯效果后
iOS 引导图的聚光灯效果代码实现_第2张图片

注:效果图中聚光灯的光圈是三级的,和代码中的稍微不一样。

你可能感兴趣的:(iOS随笔)