最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

iOS簡單畫板開發(fā)案例分享

 更新時(shí)間:2016年04月08日 09:57:32   作者:神戶牛肉  
這篇文章主要為大家分享了iOS實(shí)現(xiàn)簡單畫板開發(fā)案例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

最近在學(xué)習(xí)Quartz2D,學(xué)習(xí)了一個(gè)簡單畫板的實(shí)現(xiàn),現(xiàn)在把實(shí)現(xiàn)過程記錄一下。

主要用到的點(diǎn)就是畫線,截屏,繪制圖片,選擇圖片,以及保存所有繪制的線。

首先在storyboard上布局好控件,設(shè)置約束等等,最后的效果是這樣:

自定義畫板DrawView,使用時(shí)可能是從xib中加載,也可能是手動(dòng)創(chuàng)建,所以創(chuàng)建對象的方法需要實(shí)現(xiàn)兩個(gè):

#import <UIKit/UIKit.h>
 
@interface DrawView : UIView
/** 線寬 */
@property (nonatomic, assign) NSInteger lineWidth;
 
/** 顏色 */
@property(nonatomic, strong) UIColor *pathColor;
 
/** 圖片 */
@property(nonatomic, strong) UIImage *image;
 
- (void)clear;
 
- (void)undo;
- (void)awakeFromNib {
   
  [self setUp];
   
}
 
- (instancetype)initWithFrame:(CGRect)frame {
   
  if (self == [super initWithFrame:frame]) {
    [self setUp];
  }
  return self;
}

setUp初始化方法,初始化時(shí)要做的事情就是給畫板添加拖動(dòng)手勢,也可以將畫筆路徑的線寬在這里設(shè)置

//自定義初始化方法
- (void)setUp {
   
  //添加手勢
  UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  [self addGestureRecognizer:pan];
   
  //初始化時(shí)設(shè)置路徑線寬
  _lineWidth = 2;
   
}

手指在畫板上移動(dòng)時(shí)開始繪制線條,這里因?yàn)樵腢IBezierPath類沒有辦法設(shè)置路徑顏色,所以這里只能自定義Path類了   

#import <UIKit/UIKit.h>
 
@interface DrawPath : UIBezierPath
 
@property (nonatomic, strong) UIColor *pathColor;
 
@end

手指移動(dòng)時(shí),繪制線條,路徑是自定義的Path類

@interface DrawView ()
 
@property(nonatomic, strong)DrawPath *path;
/** 保存所有路徑的數(shù)組 */
@property(nonatomic, strong) NSMutableArray *pathArr;
 
@end
 
//懶加載
- (NSMutableArray *)pathArr {
  if (_pathArr == nil) {
     
    _pathArr = [NSMutableArray array];
     
  }
  return _pathArr;
}
- (void)pan:(UIPanGestureRecognizer *)pan {
   
  //獲取開始的觸摸點(diǎn)
  CGPoint startP = [pan locationInView:self];
   
  if (pan.state == UIGestureRecognizerStateBegan) {
     
    //創(chuàng)建貝塞爾路徑
    _path = [[DrawPath alloc]init];
    _path.lineWidth = _lineWidth;
    _path.pathColor = _pathColor;
     
    //不能在手指抬起時(shí)將路徑添加到數(shù)組,因?yàn)樵诒闅v數(shù)組畫線時(shí)路徑還沒有被添加到數(shù)組里面
    [_pathArr addObject:_path];
     
    //設(shè)置起點(diǎn)
    [_path moveToPoint:startP];
     
  }
   
  //連線
  [_path addLineToPoint:startP];
   
  //重繪,調(diào)用drawRect方法
  [self setNeedsDisplay];
   
}

畫線實(shí)現(xiàn)drawRect方法,繪制線條或者圖片時(shí),是把數(shù)組中的路徑全部畫出來

- (void)drawRect:(CGRect)rect {
   
  //把所有路徑畫出來
  for (DrawPath *path in self.pathArr) {
     
    if ([path isKindOfClass:[UIImage class]]) {
      //畫圖
      UIImage *image = (UIImage *)path;
      [image drawInRect:rect];
    }else {
      //畫線
      [path.pathColor set];
      [path stroke];
    }
  }
   
}

當(dāng)把圖片添加到畫板時(shí)

- (void)setImage:(UIImage *)image {
   
  _image = image;
   
  [self.pathArr addObject:image];
   
  //重繪調(diào)用drawRect才能在畫板上顯示圖片
  [self setNeedsDisplay];
}

還可以把直接更新路徑數(shù)組的操作封裝在畫板中

- (void)clear {
  //清除
  [self.pathArr removeAllObjects];
   
  [self setNeedsDisplay];
   
}
 
- (void)undo {
  //撤銷
  [self.pathArr removeLastObject];
   
  [self setNeedsDisplay];
}

控制器中:

@interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (weak, nonatomic) IBOutlet DrawView *drawView;
@end

實(shí)現(xiàn)幾個(gè)按鈕對畫板的操作:

- (IBAction)clear:(id)sender {
   
  //清屏
  [_drawView clear];
   
}
 
- (IBAction)undo:(id)sender {
   
  //撤銷
  [_drawView undo];
   
}
 
- (IBAction)eraser:(id)sender {
   
  //擦除 就是把路徑的顏色設(shè)置為畫板的背景色,假象
  _drawView.pathColor = _drawView.backgroundColor;
  _drawView.lineWidth = 20;
   
}
 
- (IBAction)changeLineWidth:(UISlider *)sender {
   
  //改變路徑線寬
  _drawView.lineWidth = sender.value;
   
}
 
- (IBAction)changeColor:(UIButton *)sender {
   
   
  //改變路徑顏色
  _drawView.pathColor = sender.backgroundColor;
   
}
 
- (IBAction)pickPhoto:(id)sender {
   
  //選擇照片
  //彈出系統(tǒng)相冊
  UIImagePickerController *picker = [[UIImagePickerController alloc]init];
   
  //設(shè)置選擇控制器的來源 UIImagePickerControllerSourceTypeSavedPhotosAlbum:照片庫
  picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
   
  //設(shè)置代理
  picker.delegate = self;
   
  //modal出控制器
  [self presentViewController:picker animated:YES completion:nil];
   
}
 
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
   
  //獲取選擇的圖片
  UIImage *image = info[UIImagePickerControllerOriginalImage];
   
  //創(chuàng)建一個(gè)處理圖片的view
  ImageHandleView *handleView = [[ImageHandleView alloc]initWithFrame:self.drawView.bounds];
   
  handleView.handleCompletionBlock = ^(UIImage *image){
     
    _drawView.image = image;
  };
   
  [self.drawView addSubview:handleView];
   
  //將圖片畫在畫板上
  handleView.image = image;
   
  //_drawView.image = image;
   
  //dismiss
  [self dismissViewControllerAnimated:YES completion:nil];
  //NSLog(@"%@", info);
   
}
 
- (IBAction)save:(id)sender {
   
  [UIView animateWithDuration:0.15 animations:^{
    //保存當(dāng)前畫板上的內(nèi)容
     
    //開啟上下文
    UIGraphicsBeginImageContextWithOptions(_drawView.bounds.size, NO, 0);
     
    //獲取位圖上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
     
    //把控件上的圖層渲染到上下文
    [_drawView.layer renderInContext:ctx];
     
    //獲取上下文中的圖片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
     
    //關(guān)閉上下文
    UIGraphicsEndImageContext();
     
    //保存圖片到相冊
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
     
    self.drawView.alpha = 0;
  } completion:^(BOOL finished) {
    [UIView animateWithDuration:0.15 animations:^{
      self.drawView.alpha = 1;
    }];
  }];
   
}
 
//保存成功后的方法必須是這個(gè),不能隨便寫
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
   
  NSLog(@"保存成功");
   
}

從相冊選擇完圖片后把圖片顯示在畫板上了但是還沒有渲染到layer,這時(shí)候需要對圖片進(jìn)行移動(dòng)縮放旋轉(zhuǎn)這些操作的話,但是UIImage是不能拉伸旋轉(zhuǎn)這些操作的,UIImageView才可以,所以解決思路就是自定義一個(gè)view來專門處理對圖片的操作,在自定義view上放一個(gè)UIImageView,從相冊選擇圖片后獲取的image設(shè)置給UIImageView,這樣的自定義view上操作UIIamgeView。

#import <UIKit/UIKit.h>
 
@interface ImageHandleView : UIView
/** 圖片 */
@property(nonatomic, strong) UIImage *image;
 
/** block */
@property(nonatomic, strong) void(^handleCompletionBlock)(UIImage *image);
@end
#import "ImageHandleView.h"
 
@interface ImageHandleView () <UIGestureRecognizerDelegate>
 
/** image */
@property(nonatomic, weak) UIImageView *imageView;
 
@end
 
@implementation ImageHandleView
 
//防止圖片上的觸摸事件傳遞到畫板
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
   
  return _imageView;
}
 
- (UIImageView *)imageView {
   
  if (_imageView == nil) {
    UIImageView *imageV = [[UIImageView alloc]initWithFrame:self.bounds];
     
    _imageView = imageV;
     
    //設(shè)置imgaeview允許與用戶交互
    _imageView.userInteractionEnabled = YES;
     
    //添加手勢
    [self setUpGestureRecognizer];
     
    //把這個(gè)imageview添加到圖片處理的view上
    [self addSubview:imageV];
     
  }
  return _imageView;
}
 
#pragma mark - 添加手勢
- (void)setUpGestureRecognizer {
   
  //平移手勢
  UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  [_imageView addGestureRecognizer:pan];
   
  //旋轉(zhuǎn)手勢
  UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
  rotation.delegate = self;
  [_imageView addGestureRecognizer:rotation];
   
  //縮放手勢
  UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
  pinch.delegate = self;
  [_imageView addGestureRecognizer:pinch];
   
  //長按手勢
  UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
  [_imageView addGestureRecognizer:longPress];
   
}
 
#pragma mark - 處理平移手勢
- (void)pan:(UIPanGestureRecognizer *)pan {
   
  //獲取手指的偏移量
  CGPoint tranp = [pan translationInView:self.imageView];
   
  //設(shè)置imageview的形變
  self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, tranp.x, tranp.y);
   
  //復(fù)位
  [pan setTranslation:CGPointZero inView:self.imageView];
   
}
 
#pragma mark - 處理旋轉(zhuǎn)手勢
- (void)rotation:(UIRotationGestureRecognizer *)rotation {
   
  //設(shè)置imageview的形變
  self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation.rotation);
   
  //復(fù)位
  rotation.rotation = 0;
   
}
 
#pragma mark - 處理縮放手勢
- (void)pinch:(UIPinchGestureRecognizer *)pinch {
   
  //設(shè)置imageview的形變
  self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale);
   
  //復(fù)位
  pinch.scale = 1;
   
}
 
#pragma mark - 處理長按手勢
- (void)longPress:(UILongPressGestureRecognizer *)longPress {
   
  //圖片處理完成
  if (longPress.state == UIGestureRecognizerStateBegan) {
     
    //高亮效果
    [UIView animateWithDuration:0.25 animations:^{
      self.imageView.alpha = 0;
    } completion:^(BOOL finished) {
      
      [UIView animateWithDuration:0.25 animations:^{
        self.imageView.alpha = 1;
      } completion:^(BOOL finished) {
         
        //高亮?xí)r生成一張新的圖片
        //開啟位圖上下文
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);
         
        //獲取位圖上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();
         
        //把控件的圖層渲染到上下文
        [self.layer renderInContext:ctx];
         
        //從上下文中獲取新的圖片
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
         
        //關(guān)閉上下文
        UIGraphicsEndImageContext();
         
        //調(diào)用block
        if(_handleCompletionBlock) {
          _handleCompletionBlock(image);
        }
         
        //移除父控件
        [self removeFromSuperview];
         
      }];
       
    }];
     
     
  }
   
}
 
#pragma mark - 手勢代理方法 <UIGestureRecognizerDelegate>
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
   
  //yes表示同時(shí)支持多個(gè)手勢
  return YES;
   
}
 
- (void)setImage:(UIImage *)image {
   
  _image = image;
   
  //把圖片展示到UIImageView上
  self.imageView.image = image;
 
}
 
@end

需要注意的是,當(dāng)長按將操作過的圖片繪制都畫板上生成一張新的圖片后,這時(shí)候需要把這個(gè)image設(shè)置給畫板drawView,但是這時(shí)候就必須要在專門處理圖片的view中去import畫板view,這樣耦合性太強(qiáng)。所以為了解耦,可以使用代理或者Block。我用了Block將剛剛生成的image先保存起來,在控制器中初始化imageHandleView之后再賦值給drawView。

最后保存畫板上的內(nèi)容就是將畫板上的內(nèi)容生成圖片保存到相冊即可。注意,保存完之后執(zhí)行的方法必須是這個(gè):

復(fù)制代碼 代碼如下:
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;

最后效果圖是這樣的:

以上就是本文的全部內(nèi)容,希望對大家學(xué)習(xí)iOS程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • ios多種語言的本地化思路

    ios多種語言的本地化思路

    ios程序?qū)崿F(xiàn)多種語言的本地化辦法,最近要對一款游戲進(jìn)行多語言本地化,在網(wǎng)上找了一些方案,加上自己的一點(diǎn)點(diǎn)想法整理出一套方案和大家分享!
    2015-05-05
  • iOS中大尺寸圖片的旋轉(zhuǎn)與縮放實(shí)例詳解

    iOS中大尺寸圖片的旋轉(zhuǎn)與縮放實(shí)例詳解

    圖片縮小旋轉(zhuǎn)是我們在開發(fā)中經(jīng)常會(huì)遇到的一個(gè)功能,下面這篇文章主要給大家介紹了關(guān)于iOS中大尺寸圖片的旋轉(zhuǎn)與縮放的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧
    2018-09-09
  • iOS實(shí)現(xiàn)電商購物車界面示例

    iOS實(shí)現(xiàn)電商購物車界面示例

    這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)一個(gè)類似電商購物車界面示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • iOS中導(dǎo)航欄的基本使用匯總

    iOS中導(dǎo)航欄的基本使用匯總

    導(dǎo)航欄作為iOS開發(fā)的一大空控件來說,是非常的重要這篇文章主要給大家介紹了關(guān)于iOS中導(dǎo)航欄的基本使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • 超全的iOS各種設(shè)備信息獲取方法總結(jié)(包括iPhone8/iPhone X)

    超全的iOS各種設(shè)備信息獲取方法總結(jié)(包括iPhone8/iPhone X)

    這篇文章主要給大家介紹了關(guān)于iOS各種設(shè)備信息獲取方法,iPhone8/iPhone X的后驅(qū)詳細(xì)信息也已更新,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • IOS 自定義UICollectionView的頭視圖或者尾視圖UICollectionReusableView

    IOS 自定義UICollectionView的頭視圖或者尾視圖UICollectionReusableView

    這篇文章主要介紹了IOS 自定義UICollectionView的頭視圖或者尾視圖UICollectionReusableView的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • 總結(jié)適配IOS10開發(fā)需要注意的問題

    總結(jié)適配IOS10開發(fā)需要注意的問題

    本篇文章主要介紹了適配IOS10需要注意的問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧。
    2016-12-12
  • IOS 簽名錯(cuò)誤codesign failed with exit code 1解決方法

    IOS 簽名錯(cuò)誤codesign failed with exit code 1解決方法

    這篇文章主要介紹了IOS 簽名錯(cuò)誤codesign failed with exit code 1解決方法的相關(guān)資料,遇到同樣問題的朋友可以看下,這里提供了解決方案,需要的朋友可以參考下
    2017-01-01
  • iOS下拉、上拉刷新控件的封裝

    iOS下拉、上拉刷新控件的封裝

    這篇文章主要為大家詳細(xì)介紹了iOS下拉、上拉刷新控件的封裝,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • IOS 打包出現(xiàn)Missing Push Notification Entitlement 問題解決方案

    IOS 打包出現(xiàn)Missing Push Notification Entitlement 問題解決方案

    這篇文章主要介紹了IOS 打包出現(xiàn)Missing Push Notification Entitlement 問題解決方案的相關(guān)資料,需要的朋友可以參考下
    2016-12-12

最新評論

内江市| 远安县| 静安区| 城市| 神木县| 日喀则市| 长武县| 海原县| 泗洪县| 商都县| 革吉县| 衡东县| 通辽市| 株洲县| 绥宁县| 晋宁县| 萍乡市| 肃南| 淮滨县| 留坝县| 齐河县| 敦煌市| 泰宁县| 本溪| 德化县| 卢湾区| 梁山县| 闵行区| 昌图县| 五寨县| 大兴区| 阿坝县| 高要市| 云安县| 绥江县| 洛宁县| 娱乐| 巴塘县| 奉化市| 海门市| 安岳县|