iOS绘制图形实战

Posted 太书红叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS绘制图形实战相关的知识,希望对你有一定的参考价值。

本文结构:想看吐槽直接跳到末尾。

  • 前言
  • 正文
  • 结尾扯犊子

前言

最近做了ios开发。

当一天和尚撞一天钟呗。身心俱疲。贼难受,没看我都不更新博客了么。

iOS的绘制,看了好多帖子,忘了都是哪些帖子了,感谢前辈们。不贴看过的链接了,因为看得太多了。

要是片的话,看过多少我都能熟记于心。那手法,那。。。不说了。

结尾扯点犊子,唠点嗑,也就行了。

正文

需求

最近接到这样一个需求。需求中有一个地方是这样的:
这个地方没有给背景图,看了一下基本都是直线,那就自己画一个吧,iOS还不会自定义view呢,正好熟悉一下绘制。

发现他们是排着队,一个一个插着下一个人的后面吗,这样就考虑计算一下上一个图形的尖尖插了自己的pp,所带来的影响,再来画下一个图形了。

实现思路

刚开始就想着自己绘制,那就需要新建一个继承自UIview的控件,然后开始画线,然后再绘制文字。

后来动起手来发现,文字部分不如直接用UILabel,来的快,他的sizeToFit也方便我们测量他的宽高。

于是思路变成了这样:
定义一个数组变量,由外部传入,为需要的文本数组,如图中的”好友如\\n何助力“、”打开分享链接“等。遍历此数组,实例化UIlabel,根据UIlabel的宽高计算出要画的线的各个坐标。

定义两个颜色,开始颜色和结束颜色,外部传入此控件中。获取颜色的rgb值,遍历数组时,设置对应的颜色。

如图所示:每一个图形都需要计算6个点,画5条线,需要特殊处理的地方就是第一个图形,他在计算的时候,不用受上一个图形的影响,只需要计算5个点,因为他不像其他的图形,有上一个的尖尖插着自己的pp。

最后一个图形,可以不画这个尖尖,也可以画出来,然后利用setMasksToBounds。

有了思路就开始做了。

代码

我的代码为什么是红色的
.h文件:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface BRStepView : UIView
@property(nonatomic,strong)NSArray *strData;
@property(nonatomic,strong)NSArray *colorArray;
@property(nonatomic,strong)UIColor *startColor;
@property(nonatomic,strong)UIColor *endColor;
@end

NS_ASSUME_NONNULL_END

.m文件:
CommonUtil 是个工具类,用它调用相关方法的作用大家可以顾名思义。

#import "BRStepView.h"
#import "CommonUtil.h"

@implementation BRStepView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect 
    // Drawing code

*/
//初始化
- (instancetype)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        [self setBackgroundColor:[UIColor colorWithRed:0.87 green:0.87 blue:0.87 alpha:1]];
    
    return self;

//绘制的主要方法
- (void)drawRect:(CGRect)rect

    if (!self.strData) 
    //self.strData这个就是数据源,没有数据源,不进行绘制。
        return;
    
    //定义起始、终止颜色的rgb值
    CGFloat red = 0.0;
    CGFloat green = 0.0;
    CGFloat blue = 0.0;
    CGFloat alpha = 0.0;
    CGFloat endRed = 0.0;
    CGFloat endGreen = 0.0;
    CGFloat endBlue = 0.0;
    CGFloat endAlpha = 0.0;
    if (self.startColor && self.endColor) 
    	//没设置就是0,也就是默认黑色
    	//获取rgb值:
        [self.startColor getRed:&red green:&green blue:&blue alpha:&alpha];
        [self.endColor getRed:&endRed green:&endGreen blue:&endBlue alpha:&endAlpha];
    
    CGContextRef con = UIGraphicsGetCurrentContext();//获取绘制的上下文,每一个绘制方法都需要此参数
    CGContextSetLineWidth(con, 1.0);//设置绘制的线宽
    CGFloat pointX = 0;//label的x
    CGFloat pointTopX = 0;//顶部的点
    NSInteger count = self.strData.count;
    for (int i = 0; i < self.strData.count; i++) 
    //每个颜色的值的算法:因为是要进行平均的变色,来达到循序渐进的效果。所以用起始的rgb值-终止的gbr值。所得值除以总数,算出每两个图形之间的颜色差值,根据是第几个就乘以几。然后再加上起始颜色的rgb的值,就是当前要设置的颜色。注意,alpha不用变?。
        UIColor *color = [UIColor colorWithRed:(fabs(red-endRed)/count*(i+1) + MIN(red, endRed)) green:(fabs(green-endGreen)/count*(i+1) + MIN(green,endGreen)) blue:(fabs(blue-endBlue)/count*(i+1) + MIN(blue, endBlue)) alpha:1];
        [color set];
        UILabel *label = [[UILabel alloc]init];
        [label setFont:[CommonUtil getFontWithFontName:@"PingFangSC-Regular" andFontSize:12]];
        [label setTextColor:[CommonUtil colorWithHexString:@"#333333"]];
        NSString *text = self.strData[i];
        [label setText:text];
        [label setNumberOfLines:0];
        [label sizeToFit];//下面会利用label的frame来计算
        [self addSubview:label];
        CGContextSetFillColorWithColor(con, color.CGColor);//线颜色
        CGContextMoveToPoint(con, pointTopX, 0);//起始点
        if (i == 0) //第一个图形,不用计算上一个图形的尖尖
            CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5, 0);//label左测留白10右侧留白5,留白就是传说中的margin
            if (i != self.strData.count - 1)//不是最后一个
            
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15, CGRectGetHeight(self.frame)/2);
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5, CGRectGetHeight(self.frame));
            
            else
            //最后一个不画这个尖,直接画到头
                CGContextAddLineToPoint(con, CGRectGetWidth(self.frame) + 10 + 5, CGRectGetHeight(self.frame));
            
            CGContextAddLineToPoint(con, pointTopX, CGRectGetHeight(self.frame));
        else//非第一个图形,需要计算上一个图形的尖尖,因为他插了自己pp。
            if (i != self.strData.count - 1)
            
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15, 0);//label再加前一个尖
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15 + 15, CGRectGetHeight(self.frame)/2);
                CGContextAddLineToPoint(con, pointTopX + CGRectGetWidth(label.frame) + 10 + 5 + 15, CGRectGetHeight(self.frame));
            
            else
            //最后一个不画这个尖,直接画到头
                CGContextAddLineToPoint(con, CGRectGetWidth(self.frame), 0);//label再加前一个尖
                CGContextAddLineToPoint(con, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
            
            CGContextAddLineToPoint(con, pointTopX, CGRectGetHeight(self.frame));
            CGContextAddLineToPoint(con, pointTopX + 15, CGRectGetHeight(self.frame)/2);
        
        CGContextFillPath(con);//封闭,关门放狗
        //开始计算下一个图形的相关位置
        if (i != 0) //第一个图形,不用计算上一个图形的尖尖
            pointTopX = pointTopX + CGRectGetWidth(label.frame) + 10 + 5 +15;//label左10右5 尖15
        else//非第一个图形,需要计算上一个图形的尖尖,因为他插了自己pp。
            pointTopX = pointTopX + CGRectGetWidth(label.frame) + 10 + 5;//label左10右5
        
        pointX += 10;//左侧10
        //放置奇兵
        label.center = CGPointMake(pointX + CGRectGetWidth(label.frame)/2, CGRectGetHeight(self.frame)/2);
        pointX += CGRectGetWidth(label.frame) +5;
        pointX += 15;
    

@end

代码写的垃圾,刷几天LeetCode吧。今天看到一个LeetCode的快速刷题的插件,想试试。真好。

扯犊子

在这扯:
https://blog.csdn.net/u014540814/article/details/87855504

以上是关于iOS绘制图形实战的主要内容,如果未能解决你的问题,请参考以下文章

R语言gap.plot函数绘制坐标轴有隔断的可视化图形实战

R语言使用ggpubr包绘制出版社编辑审稿人要求的可视化图形实战

OpenCV-Python实战——OpenCV中绘制图形与文本(万字总结,️❤️建议收藏️❤️)

R语言可视化包ggplot2包绘制多个图形并将多个图像垂直堆叠c成一个图像实战(grid.arrange)

iOS的基本图形绘制

iOS 图形绘制(二)-UIBezierPath