iOS 多层渐变绘制

1. 背景

UI设计使用渐变色是常规操作无法避免,虽然我们希望设计MM使用容易实现的横向或竖向简单单层渐变,然儿现实中你会遇到下面的情况:

  • 1、非 0°、90°、180°、270°等直线角度,如158.08°等斜角

    image.png
  • 2、开始位置和结束位置不在边线上
  • 3、多层渐变或多层+斜角渐变

    image.png
  • 4、使用图片实现效果会增大.ipa包体积

    image.png

当代码不好实现的时候,我们往往想到直接使用图片满足效果,然儿直接使用图片会增大.ipa包体积,图片拉伸之后显示变形等问题。所以能否通过Figma多层渐变css参数,直接绘制出图层,像H5一样方便在代码中使用。

为了解决上面的问题,根据Figma中css参数UIColor分类中封装一个方法,帮我们实现了一个支持单层、多层线性渐变背景,极大地减少了对图片资源的依赖,有效提升 App 性能和 UI 一致性。

组件功能的亮点:

  • 支持多层线性渐变叠加
  • 支持各种角度
  • 支持设置locations
  • 配合Figma上css参数,直接设置好对应参数即可

API 介绍

  • API定义

    image.png
  • API实现
+ (UIColor *)multiGradientWithSize:(CGSize)size gradients:(NSArray<NSDictionary *> *)gradientSpecs {
    if (size.width < 1 || size.height < 1) return nil;
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    if (!context) return nil;
    
    // Draw each gradient specification
    for (NSDictionary *gradientSpec in gradientSpecs) {
        // Extract parameters from the gradient specification
        NSArray *colors = gradientSpec[@"colors"];
        NSArray <NSNumber *>*locations = gradientSpec[@"locations"];
        if (colors.count == 0 || !gradientSpec[@"angle"]) {
            continue;
        }
        CGFloat angle = [gradientSpec[@"angle"] doubleValue];
        
        // Convert angle to start/end points
        CGFloat radians = (angle - 90) * M_PI / 180.0; // Convert to radians and adjust for Core Graphics coordinate system
        CGFloat centerX = size.width / 2.0;
        CGFloat centerY = size.height / 2.0;
        CGFloat length = sqrt(size.width * size.width + size.height * size.height) / 2.0;
        
        CGPoint startPoint = CGPointMake(centerX - cos(radians) * length, centerY - sin(radians) * length);
        CGPoint endPoint = CGPointMake(centerX + cos(radians) * length, centerY + sin(radians) * length);
        
        NSMutableArray *cgColors = [NSMutableArray array];
        for (UIColor *color in colors) {
            [cgColors addObject:(id)color.CGColor];
        }
        
        NSUInteger count = locations.count;
        CGFloat *locationArray = malloc(sizeof(CGFloat) * count);
        for (NSUInteger i = 0; i < count; i++) {
            locationArray[i] = locations[i].floatValue;
        }
        CGGradientRef gradient = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), (__bridge CFArrayRef)cgColors,count > 0 ? locationArray : NULL);
        free(locationArray);
        
        CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
        
        CGGradientRelease(gradient);
    }
    
    UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return [UIColor colorWithPatternImage:gradientImage];
}

使用示例

  1. 获取渐变参数值,如:

    image.png

值:

background: linear-gradient(134.83deg, #BDD9FE 0%, #ECF2FA 100%),
linear-gradient(42.71deg, rgba(255, 255, 255, 0) 46%, #CFEEF5 98.72%),
linear-gradient(205.29deg, rgba(237, 241, 252, 0) 53.38%, #EDF1FC 100%);
  1. 调用 + (UIColor *)multiGradientWithSize:(CGSize)size gradients:(NSArray<NSDictionary *> *)gradientSpecs 方法
image.png
(完结~)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,785评论 1 180
  • """1.个性化消息: 将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello ...
    她即我命阅读 3,324评论 0 5
  • 为了让我有一个更快速、更精彩、更辉煌的成长,我将开始这段刻骨铭心的自我蜕变之旅!从今天开始,我将每天坚持阅...
    李薇帆阅读 1,973评论 0 3
  • 似乎最近一直都在路上,每次出来走的时候感受都会很不一样。 1、感恩一直遇到好心人,很幸运。在路上总是...
    时间里的花Lily阅读 1,418评论 0 2
  • 1、expected an indented block 冒号后面是要写上一定的内容的(新手容易遗忘这一点); 缩...
    庵下桃花仙阅读 554评论 0 1