详解iOS App中图片的线段涂鸦功能的添加方法

接下来我们要讲图片的涂鸦,我们分开一点一点拓展,先给图片上划线
创建项目 起名testAddLine

接下来我们在默认生成的ViewController中添加一张图片 待用
同时添加一个按钮


代码如下:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
     
    UIImageView *imageV = [[UIImageView alloc]initWithFrame:CGRectMake(10, 120, screen_Width-20, screen_Height-150)]; 
    imageV.image = [UIImage imageNamed:@"640-960-1.jpg"]; 
    [self.view addSubview:imageV]; 
     
    UIButton *testBtn = [[UIButton alloc]initWithFrame:CGRectMake(screen_Width/2.0-60, 60, 120, 36)]; 
    [testBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 
    [testBtn setTitle:@"添加直线" forState:UIControlStateNormal]; 
    [testBtn addTarget:self action:@selector(addLineAct:) forControlEvents:UIControlEventTouchUpInside]; 
    [self.view addSubview:testBtn]; 

 
- (void)addLineAct:(id)sender{ 
    NSLog(@"测试按钮"); 
}

接下来我们创建一个UIView 用来添加直线 起名:DrawLine

创建几个变量


代码如下:

@property(nonatomic,strong) NSMutableArray * completeLines; //已经画好的线条 存入数组 
@property(nonatomic,strong) NSMutableDictionary* LinesInProscess; //正在画的线条 存入字典 
@property(nonatomic,strong) UIColor *lineColor;//线条颜色 
@property (nonatomic)float lineWidth;//线条的粗细

初始化DrawLine

代码如下:

//初始化 
- (id)initWithFrame:(CGRect)frame{ 
    if (self = [super initWithFrame:frame]) { 
        //初始化变量 
        _completeLines = [[NSMutableArray alloc]init]; 
        _LinesInProscess = [[NSMutableDictionary alloc]init]; 
        //设置透明背景 
        self.backgroundColor = [UIColor clearColor]; 
         
    } 
     
    return  self; 
}

我们把线条单独抽象出来 创建一个类 创建对象 起名 Line

线条 两个属性 起始点 结束点(这就是数学中的两点确定一条直线)
给Line 类创建两个属性


代码如下:

#import <Foundation/Foundation.h> 
#import <UIKit/UIKit.h> 
 
@interface Line : NSObject 
 
@property(nonatomic)CGPoint begin; //线条开始点 
 
@property(nonatomic)CGPoint end; //线条结束点 
 
@end

接下来 我们重写DrawLine 的  drawRect 方法  绘制线条

代码如下:

// Only override drawRect: if you perform custom drawing. 
// An empty implementation adversely affects performance during animation. 
- (void)drawRect:(CGRect)rect { 
    // Drawing code 
     
    //获取上下文 
    CGContextRef cgt=UIGraphicsGetCurrentContext(); 
    //设置线条宽度 
    CGContextSetLineWidth(cgt, self.lineWidth); 
    //设置线条两端形状为圆角 
    CGContextSetLineCap(cgt, kCGLineCapRound); 
     
    //设置颜色 
    [self.lineColor set]; 
    //绘制已经完成的线段 
    for (Line *line in _completeLines){ 
        CGContextMoveToPoint(cgt, [line begin].x, [line begin].y); 
        CGContextAddLineToPoint(cgt, [line end].x, [line end].y ); 
        CGContextStrokePath(cgt); 
    } 
     
     
    //绘制正在画的线段 
    for (NSArray *v in _LinesInProscess) { 
        Line *line =[_LinesInProscess objectForKey:v]; 
        CGContextMoveToPoint(cgt, [line begin].x, [line begin].y); 
        CGContextAddLineToPoint(cgt, [line end].x, [line end].y ); 
        CGContextStrokePath(cgt); 
    } 
     
}

实现几个手指滑动方法 用来接受手指的位置画线

代码如下:

//清空画板 
-(void)clearAll 

    [_completeLines removeLastObject]; 
    [_LinesInProscess removeAllObjects]; 
    [self setNeedsDisplay]; 

 
 
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 

    //判断是否连按 
    for (UITouch *t in touches) { 
        if ([t tapCount]>1) { 
            //第二次画线时第一条线还未完成时结束画线 
            [self clearAll]; 
            return; 
        } 
         
        //NSValue 作为键使用 
        NSValue *key=[NSValue valueWithNonretainedObject:t]; 
         
        // 根据触摸位置创建Line对象 
        CGPoint loc=[t locationInView:self]; 
        Line *newLine=[[Line alloc]init ]; 
        newLine.begin=loc; 
        newLine.end=loc; 
        //将当前正在画的线存入字典 
        [_LinesInProscess setObject:newLine forKey:key]; 
         
    } 

 
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 

    //手指移动过程中按照当前手指的位置动态更新线条 
    for (UITouch * t in touches) { 
        NSValue *key=[NSValue valueWithNonretainedObject:t]; 
        // 找对象当前UITouch对象的Line对象 
        Line *line =[_LinesInProscess objectForKey:key]; 
         
        CGPoint loc=[t locationInView:self]; 
        line.end=loc; 
    } 
    [self setNeedsDisplay]; 

 
-(void)endTouches:(NSSet *) touches 

    //画线完成之后将当前线条加入_completeLines 数组中 同时删除字典_LinesInProscess里的线条 
    for (UITouch *t in touches) { 
        NSValue *key=[NSValue valueWithNonretainedObject:t]; 
        Line *line =[_LinesInProscess objectForKey:key]; 
        if (line) { 
            [_completeLines addObject:line]; 
            [_LinesInProscess removeObjectForKey:key]; 
        } 
    } 
    [self setNeedsDisplay]; 

 
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 

    [self endTouches:touches]; 

 
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 

    [self endTouches:touches]; 
}

回到 ViewController中 给按钮点击事件中 添加DrawLine到ImageView上

代码如下:

- (void)addLineAct:(id)sender{ 
    NSLog(@"测试按钮"); 
     
    DrawLine *touchdrawView = [[DrawLine alloc]initWithFrame:imageV.frame]; 
 
    touchdrawView.lineColor = [UIColor yellowColor]; 
    touchdrawView.lineWidth = 5.0; 
    touchdrawView.tag = 902; 
    [self.view addSubview:touchdrawView]; 
     
     
}

好了 运行程序试试
点击 添加直线 按钮之后 试试在图片上画线

带剪头的线条
在上面例子的基础上稍微拓展一下,给线段末尾加上一个箭头
给DrawLine 类中添的方法 drawRect 中添加一段代码

代码如下:

//添加剪头 
double r = sqrt((line.end.x-line.begin.x)*(line.end.x-line.begin.x)+(line.begin.y-line.end.y)*(line.begin.y-line.end.y));//线条长度 
CGContextMoveToPoint(cgt,line.end.x,line.end.y); 
//P1 
CGContextAddLineToPoint(cgt,line.end.x-(10*(line.begin.y-line.end.y)/r),line.end.y-(10*(line.end.x-line.begin.x)/r)); 
//P3 
CGContextAddLineToPoint(cgt,line.end.x+(20*(line.end.x-line.begin.x)/r), line.end.y-(20*(line.begin.y-line.end.y)/r)); 
//P2 
CGContextAddLineToPoint(cgt,line.end.x+(10*(line.begin.y-line.end.y)/r),line.end.y+(10*(line.end.x-line.begin.x)/r)); 
 
CGContextAddLineToPoint(cgt, line.end.x,line.end.y); 
CGContextDrawPath(cgt,kCGPathFillStroke); 
CGContextStrokePath(cgt);

以上方法的思路 就是在线段画完之后 确定三个点 画一个三角形作为箭头形状

(0)

相关推荐

  • iOS实现无限循环图片轮播器的封装

    项目中很多时候会碰到这个需求,实现多张图片的无限循环轮转,以前做过,项目中几个地方的都用到了,当时没有封装,几个地方都拷贝几乎一样的代码,代码复用性不好,今天没事封装了一下,使用起来比较简单. 首先,说说我实现循环轮转图片的思想,在UIScrollView中添加了3个UIImageView,并排排列,我们看到的永远只是第二个UIImageView,这样的话,你一直可以向左,向右滑动,当你向左滑动是,这是你滑动到了最后一个UIImageView不能在向左边滑动了,这时,我在后面悄悄的将第二个UII

  • 改变iOS应用中UITableView的背景颜色与背景图片的方法

    改变UITableView的header.footer背景颜色 改变UITableView的header.footer背景颜色,这是个很常见的问题.之前知道的一般做法是,通过实现tableView: viewForHeaderInSection:返回一个自定义的View,里面什么都不填,只设背景颜色.但是今天发现一个更简洁的做法: 对于iOS 6及以后的系统,实现这个新的delegate函数即可: 复制代码 代码如下: - (void)tableView:(UITableView *)table

  • iOS实现文字转化成彩色文字图片

    本文写了个将文字转化为多彩图片的功能,输入文字将文字转化为彩色的文字图片,可选择不同的字体,渐变,先看看效果. 实现主要用CAGradientLayer渐变,先看看上部展示实现代码: -(void)setupContentView { UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, ScreenWidth, ScreenHight - 44 -300)]; [self.view addSubview:co

  • IOS多线程实现多图片下载(一)

    在没有步入正文之前先给大家展示下效果图,如果大家觉得很满意请继续往下阅读全文. 大家可以看到这个界面很简单,其实就是UITableView的布局,但是难点是在于如何从网上下载这些图片,下载之后应如何进行存储! 我们一步一步进行解析,先从单线程(主线程)进行多图片下载我们布局上的文字及图片的地址从plist文件中进行读取 根据结构,我们自定义一个数据模型文件 DDZApp.h #import <Foundation/Foundation.h> @interface DDZApp : NSObje

  • iOS实现裁剪框和图片剪裁功能

    图片处理中经常用的图片剪裁,就是通过剪裁框确定图片剪裁的区域,然后剪去该区域的图片,今天实现了一下,其实图片剪裁本身不难,主要剪裁框封装发了点时间,主要功能可以拖动四个角缩放,但不能超出父视图,拖动四个边单方向缩放,不能超出父视图,拖动中间部分单单移动,不改变大小,不能超出父视图.下面列举一些主要代码. 四个角的处理代码: -(void)btnPanGesture:(UIPanGestureRecognizer*)panGesture { UIView *vw = panGesture.view

  • IOS图片无限轮播器的实现原理

    首先实现思路:整个collectionView中只有2个cell.中间始终显示第二个cell. 滚动:向前滚动当前cell的脚标为0,向后滚动当前的cell脚标为2.利用当前cell的脚标减去1,得到+1,或者-1,来让图片的索引加1或者减1,实现图片的切换. 声明一个全局变量index来保存图片的索引,用来切换显示在当前cell的图片. 在滚动前先让显示的cell的脚标变为1.代码viewDidLoad中设置 完成一次滚动结束后,代码再设置当前的cell为第二个cell(本质上就是让当前显示的

  • IOS图片设置毛玻璃效果

    推荐阅读:ios毛玻璃效果的实现及图片模糊效果的三种方法 废话不多说了,直接给大家贴代码了,具体代码如下所示: // 创建需要的毛玻璃特效类型 UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; // 毛玻璃view 视图 UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:blurEf

  • IOS多线程实现多图片下载(二)

    上篇文章给大家介绍了IOS多线程实现多图片下载1,本文继续给大家介绍ios多线程下载图片. 这次是用多线程进行图片的下载与存储,而且考虑到下载失败,占位图片的问题(第一张就是下载失败的图片) 闲话少说,上代码吧,因为有一部分和上次的一样,所以这里只上传不一样的 先给大家展示下效果图: 依旧都是在ViewController.m中 1. @interface ViewController () //所有数据 @property (nonatomic,strong)NSArray *apps; //

  • 深入分析iOS应用中对于图片缓存的管理和使用

    我们的 iOS 应用都包含了大量的图像.创建富有吸引力的视图,主要依赖于大量的装饰图片,所有这些首先必须从远程服务器获取.如果每次打开应用都要从服务器一次又一次的获取每个图像,那么用户体验肯定达不到好的效果,所以本地缓存远程图像是非常有必要的. 两种方式加载本地图片 1.通过imageNamed:方法加载图片 用过这种方式加载图片,一旦图片加载到内存中,那么就不会销毁,一直到程序退出.(也就是说imageNamed:会有图片缓存的功能,当下次访问图片的时候速度会更快.) 用这种方式加载图片,图片

  • iOS自定义UICollectionViewFlowLayout实现图片浏览效果

    以前瀑布流的时候使用过UICollectionView,但是那时使用的是系统自带的UICollectionViewFlowLayout布局,今天看文章,看到UICollectionViewFlowLayout自定义相关的东西,于是动手写了一个简单图片浏览的demo,熟练一些UICollectionViewFlowLayout自定义布局. #import <UIKit/UIKit.h> @interface JWCollectionViewFlowLayout : UICollectionVie

随机推荐