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 . 运行效果图展示
添加聚光灯效果前
这里写图片描述
添加聚光灯效果后
这里写图片描述

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用 `UICollectionView` 或 `UIPageViewController` 来实现 iOS 图片轮播。 使用 `UICollectionView` 实现的方法如下: 1. 在您的视控制器中,创建一个 `UICollectionView` 实例,并将其作为子视添加到您的视控制器的视中。 2. 使用自定义布局实现循环滚动。可以参考以下代码: ``` class LoopCollectionViewFlowLayout: UICollectionViewFlowLayout { override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { guard let collectionView = collectionView else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) } let collectionViewSize = collectionView.bounds.size let proposedContentOffsetCenterX = proposedContentOffset.x + collectionViewSize.width * 0.5 let proposedRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionViewSize.width, height: collectionViewSize.height) guard let layoutAttributes = layoutAttributesForElements(in: proposedRect) else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) } let centerX = proposedContentOffsetCenterX let offset = CGPoint(x: proposedContentOffset.x + nearestTargetOffset(for: layoutAttributes, with: centerX), y: proposedContentOffset.y) return offset } private func nearestTargetOffset(for layoutAttributes: [UICollectionViewLayoutAttributes], with centerX: CGFloat) -> CGFloat { let targetAttributes = layoutAttributes.sorted { abs($0.center.x - centerX) < abs($1.center.x - centerX) } let nearestAttribute = targetAttributes.first return nearestAttribute?.center.x ?? 0 - centerX } } ``` 3. 创建自定义 `UICollectionViewCell` 类,并在其中添加一个 `UIImageView` 用于显示图片。 4. 实现 `UICollectionViewDataSource` 协议中的方法,用于设置图片数据源和自定义的 `UICollectionViewCell`。 5. 实现定时器

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值