//联系人:石虎 QQ: 1224614774昵称:嗡嘛呢叭咪哄
/**
注意点: 1.看 GIF 效果图.
2.看连线视图的效果图.
3.看实现代码(直接复制实现效果).
*/
一、GIF 效果图:
二、连线视图的效果图:
图1:
图2:
图3:
图4:
图5:
三、实现代码:
=========================
===================================================
==========================控制器1: SHContext.h
//
// SHContext.h
// HandDraw(手绘)~demo
//
// Created by 石虎 on 2017/8/15.
// Copyright © 2017年 shihu. All rights reserved.
//
#ifndef SHContext_h
#define SHContext_h
/*
该方法负责绘制圆角矩形;
x1 y2:是圆角矩形左上角的座标。
width height:控制圆角举行的宽、高
radius控制圆角矩形的四个圆角的半径
*/
void CGContextAddRoundRect(CGContextRef c, CGFloat x1 , CGFloat y1
, CGFloat width , CGFloat height , CGFloat radius)
{
// 移动到左上角
CGContextMoveToPoint (c, x1 + radius , y1);
// 添加一条连接到右上角的线段
CGContextAddLineToPoint(c , x1 + width - radius, y1);
// 添加一段圆弧
CGContextAddArcToPoint(c , x1 + width , y1, x1 + width
, y1 + radius, radius);
// 添加一条连接到右下角的线段
CGContextAddLineToPoint(c , x1 + width, y1 + height - radius);
// 添加一段圆弧
CGContextAddArcToPoint(c , x1 + width, y1 + height
, x1 + width - radius , y1 + height , radius);
// 添加一条连接到左下角的线段
CGContextAddLineToPoint(c , x1 + radius, y1 + height);
// 添加一段圆弧
CGContextAddArcToPoint(c , x1, y1 + height , x1
, y1 + height - radius , radius);
// 添加一条连接到左上角的线段
CGContextAddLineToPoint(c , x1 , y1 + radius);
// 添加一段圆弧
CGContextAddArcToPoint(c , x1 , y1 , x1 + radius , y1 , radius);
}
/*
该方法负责绘制多角星。
n:该参数通常应设为奇数,控制绘制N角星。
dx、dy:控制N角星的中心。
size:控制N角星的大小
*/
void CGContextAddStar(CGContextRef c , NSInteger n
, CGFloat dx , CGFloat dy , NSInteger size)
{
CGFloat dig = 4 * M_PI / n ;
// 移动到指定点
CGContextMoveToPoint(c , dx , dy + size);
for(int i = 1 ; i <= n ; i++)
{
CGFloat x = sin(i * dig);
CGFloat y = cos(i * dig);
// 绘制从当前点连接到指定点的线条
CGContextAddLineToPoint(c , x * size + dx ,y * size + dy);
}
}
#endif /* SHContext_h */
=========================
===================================================
控制器2:SHConstant.h
//=================
//=============
//
// SHConstant.h
// HandDraw(手绘)~demo
//
// Created by 石虎 on 2017/8/15.
// Copyright © 2017年 shihu. All rights reserved.
//
#ifndef SHConstant_h
#define SHConstant_h
typedef enum
{
kLineShape = 0,
kRectShape,
kEllipseShape,
kRoundRectShape,
kPenShape
} ShapeType;
#endif /* SHConstant_h */
控制器3:SHDrawView.h
//=================
//=============
//
// SHDrawView.h
// HandDraw(手绘)~demo
//
// Created by 石虎 on 2017/8/15.
// Copyright © 2017年 shihu. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SHConstant.h"
@interface SHDrawView : UIView
@property (nonatomic, strong) UIColor* currentColor;
@property (nonatomic, assign) ShapeType shape;
@end
控制器3:SHDrawView.m
//=================
//=============
//
// SHDrawView.m
// HandDraw(手绘)~demo
//
// Created by 石虎 on 2017/8/15.
// Copyright © 2017年 shihu. All rights reserved.
//
#import "SHDrawView.h"
#import "SHContext.h"
@implementation SHDrawView
CGPoint firstTouch, prevTouch, lastTouch;
// 定义向内存中图片执行绘图的CGContextRef
CGContextRef buffCtx;
UIImage* image;
- (id)initWithCoder:(NSCoder*)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// 初始化时将当前颜色设为红色
self.currentColor = [UIColor redColor];
// 创建内存中的图片
UIGraphicsBeginImageContext(self.bounds.size);
// 获取向内存中图片执行绘图的CGContextRef
buffCtx = UIGraphicsGetCurrentContext();
}
return self;
}
// 当用户手指开始触碰时激发该方法
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
// 获取触碰点坐标
firstTouch = [touch locationInView:self];
// 如果当前正在进行自由绘制,prevTouch代表第一个触碰点
if (self.shape == kPenShape)
{
prevTouch = firstTouch;
}
}
// 当用户手指在控件上拖动时不断地激发该方法
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
// 获取触碰点坐标
lastTouch = [touch locationInView:self];
// 如果当前正在进行自由绘制
if (self.shape == kPenShape)
{
// 向内存中的图片执行绘制
[self draw:buffCtx];
// 取出内存中的图片,保存到image中
image = UIGraphicsGetImageFromCurrentImageContext();
}
// 通知该控件重绘,此时会实时地绘制起始点与用户手指拖动点之间的形状
[self setNeedsDisplay];
}
// 当用户手指离开控件时激发该方法
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
// 获取离开触碰的点坐标
lastTouch = [touch locationInView:self];
// 向内存中的图片执行绘制,即把最终确定图形绘制到内存中图片上
[self draw:buffCtx];
image = UIGraphicsGetImageFromCurrentImageContext();
// 通知重绘。
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
// 获取绘图上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 将内存中的图片绘制出来
[image drawAtPoint:CGPointZero];
// 调用draw:方法执行绘制
[self draw:ctx];
}
// 定义一个函数,用于根据firstTouch、lastTouch来确定矩形区域
- (CGRect) curRect
{
return CGRectMake(firstTouch.x, firstTouch.y,
lastTouch.x - firstTouch.x ,
lastTouch.y - firstTouch.y);
}
- (void)draw:(CGContextRef)ctx
{
// 设置线条颜色
CGContextSetStrokeColorWithColor(ctx, self.currentColor.CGColor);
// 设置填充颜色
CGContextSetFillColorWithColor(ctx, self.currentColor.CGColor);
// 设置线宽
CGContextSetLineWidth(ctx, 2.0);
CGContextSetShouldAntialias(ctx, YES);
switch (self.shape) {
CGFloat leftTopX , leftTopY;
case kLineShape:
// 添加从firstTouch到lastTouch的路径
CGContextMoveToPoint(ctx, firstTouch.x, firstTouch.y);
CGContextAddLineToPoint(ctx, lastTouch.x, lastTouch.y);
// 绘制路径
CGContextStrokePath(ctx);
break;
case kRectShape:
// 填充矩形
CGContextFillRect(ctx ,[self curRect]);
break;
case kEllipseShape:
// 填充椭圆
CGContextFillEllipseInRect(ctx ,[self curRect]);
break;
case kRoundRectShape:
// 计算左上角的坐标
leftTopX = firstTouch.x < lastTouch.x ? firstTouch.x :
lastTouch.x;
leftTopY = firstTouch.y < lastTouch.y ? firstTouch.y :
lastTouch.y;
// 添加圆角矩形的路径
CGContextAddRoundRect(ctx ,leftTopX ,leftTopY ,
fabs(lastTouch.x - firstTouch.x) ,
fabs(lastTouch.y - firstTouch.y) , 16);
// 填充路径
CGContextFillPath(ctx);
break;
case kPenShape:
// 添加从prevTouch到lastTouch的路径
CGContextMoveToPoint(ctx, prevTouch.x, prevTouch.y);
CGContextAddLineToPoint(ctx, lastTouch.x, lastTouch.y);
// 绘制路径
CGContextStrokePath(ctx);
// 使用prevTouch保存当前点
prevTouch = lastTouch;
break;
}
}
@end
控制器1: SHContext.h
//=================
//=============
控制器4:ViewController.h
//=================
//=============
//
// ViewController.h
// HandDraw(手绘)~demo
//
// Created by 石虎 on 2017/8/15.
// Copyright © 2017年 shihu. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
//改变颜色
- (IBAction)changeColor:(UISegmentedControl*)sender;
//改变形状
- (IBAction)changeShape:(UISegmentedControl*)sender;
@end
控制器4:ViewController.m
//=================
//=============
//
// ViewController.m
// HandDraw(手绘)~demo
//
// Created by 石虎 on 2017/8/15.
// Copyright © 2017年 shihu. All rights reserved.
//
#import "ViewController.h"
#import "SHDrawView.h"
@interface ViewController ()
{
NSArray *colors;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
colors = [NSArray arrayWithObjects:
[UIColor redColor],[UIColor greenColor],
[UIColor blueColor],[UIColor yellowColor],
[UIColor purpleColor],[UIColor cyanColor],
[UIColor blackColor] , nil];
}
- (IBAction)changeColor:(UISegmentedControl*)sender {
// 根据用户的选择来修改FKDrawView的当前颜色
((SHDrawView*)self.view).currentColor = [colors objectAtIndex:
sender.selectedSegmentIndex];
}
- (IBAction)changeShape:(UISegmentedControl*)sender
{
// 修改FKDrawView控件的shape属性
((SHDrawView*)self.view).shape = sender.selectedSegmentIndex;
}
@end
//===============
//=======