简介
现在很多项目在完善信息或者注册信息的时候,或者支付这一方面,都希望用户手写签名,这样既可以保证是用户亲自签名的,保证该记录是用用户操作的,而不是别人操作的.所以手写签字这个还是比较重要的.下面就是通过QuartzCore来绘制签名.QuartzCore是iOS的核心动画框架.
绘制
-
1定义一个结构体
1
2
3
4
5
6
|
static CGPoint midpoint(CGPoint p0,CGPoint p1) { return (CGPoint) { (p0.x + p1.x) / 2.0 , (p0.y + p1.y) / 2.0 }; } |
-
2添加手势
1
2
3
|
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; pan.maximumNumberOfTouches = pan.minimumNumberOfTouches = 1 ; [self addGestureRecognizer:pan]; |
-
3开始绘制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
CGPoint currentPoint = [pan locationInView:self]; CGPoint midPoint = midpoint(previousPoint, currentPoint); NSLog(@ "获取到的触摸点的位置为--currentPoint:%@" ,NSStringFromCGPoint(currentPoint)); [self.currentPointArr addObject:[NSValue valueWithCGPoint:currentPoint]]; self.hasSignatureImg = YES; CGFloat viewHeight = self.frame.size.height; CGFloat currentY = currentPoint.y; if (pan.state ==UIGestureRecognizerStateBegan) { [path moveToPoint:currentPoint]; } else if (pan.state ==UIGestureRecognizerStateChanged) { [path addQuadCurveToPoint:midPoint controlPoint:previousPoint]; } if ( 0 <= currentY && currentY <= viewHeight) { if (max == 0 &&min == 0 ) { max = currentPoint.x; min = currentPoint.x; } else { if (max <= currentPoint.x) { max = currentPoint.x; } if (min>=currentPoint.x) { min = currentPoint.x; } } } previousPoint = currentPoint; //记得调用,及时刷新视图 [self setNeedsDisplay]; |
-
4获取绘制视图,在进行一系列处理就好
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
if (UIGraphicsBeginImageContextWithOptions !=NULL) { UIGraphicsBeginImageContextWithOptions(self.bounds.size,NO, [UIScreen mainScreen].scale); } else { UIGraphicsBeginImageContext(self.bounds.size); } [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image =UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //绘制成图 image = [self imageBlackToTransparent:image]; NSLog(@ "width:%f,height:%f" ,image.size.width,image.size.height); //截取图片 UIImage *img = [self cutImage:image]; //压缩图片 self.SignatureImg = [self scaleToSize:img]; |
-
5附上处理的方法
1.绘制成图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
- (UIImage*) imageBlackToTransparent:(UIImage*) image { // 分配内存 const int imageWidth = image.size.width; const int imageHeight = image.size.height; size_t bytesPerRow = imageWidth * 4 ; uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight); // 创建context CGColorSpaceRef colorSpace =CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8 , bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast); CGContextDrawImage(context, CGRectMake( 0 , 0 , imageWidth, imageHeight), image.CGImage); // 遍历像素 int pixelNum = imageWidth * imageHeight; uint32_t* pCurPtr = rgbImageBuf; for ( int i = 0 ; i < pixelNum; i++, pCurPtr++) { // if ((*pCurPtr & 0xFFFFFF00) == 0) //将黑色变成透明 if (*pCurPtr == 0xffffff ) { uint8_t* ptr = (uint8_t*)pCurPtr; ptr[ 0 ] = 0 ; } //改成下面的代码,会将图片转成灰度 /*uint8_t* ptr = (uint8_t*)pCurPtr; // gray = red * 0.11 + green * 0.59 + blue * 0.30 uint8_t gray = ptr[3] * 0.11 + ptr[2] * 0.59 + ptr[1] * 0.30; ptr[3] = gray; ptr[2] = gray; ptr[1] = gray;*/ } // 将内存转成image CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, /*ProviderReleaseData**/ NULL); CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8 , 32 , bytesPerRow, colorSpace, kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider, NULL, true ,kCGRenderingIntentDefault); CGDataProviderRelease(dataProvider); UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef]; // 释放 CGImageRelease(imageRef); CGContextRelease(context); CGColorSpaceRelease(colorSpace); // free(rgbImageBuf) 创建dataProvider时已提供释放函数,这里不用free return resultUIImage; } |
2.截图图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
CGRect rect ; //签名事件没有发生 if (min == 0 &&max == 0 ) { rect =CGRectMake( 0 , 0 , 0 , 0 ); } else //签名发生 { rect =CGRectMake(min- 3 , 0 , max-min+ 6 ,self.frame.size.height); } CGImageRef imageRef =CGImageCreateWithImageInRect([image CGImage], rect); UIImage * img = [UIImage imageWithCGImage:imageRef]; //添加水印 UIImage *lastImage = [self addText:img text:self.showMessage]; CGImageRelease(imageRef); [self setNeedsDisplay]; |
3.压缩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//压缩图片,最长边为128(根据不同的比例来压缩) - (UIImage *)scaleToSize:(UIImage *)img { CGRect rect ; CGFloat imageWidth = img.size.width; //判断图片宽度 if (imageWidth >= 128 ) { rect =CGRectMake( 0 , 0 , 128 , self.frame.size.height); } else { rect =CGRectMake( 0 , 0 , img.size.width,self.frame.size.height); } CGSize size = rect.size; UIGraphicsBeginImageContext(size); [img drawInRect:rect]; UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //此处注释是为了防止该签名图片被保存到本地 // UIImageWriteToSavedPhotosAlbum(scaledImage,nil, nil, nil); [self setNeedsDisplay]; return scaledImage; } |
剩下的,都是一些细节问题,根据不同的项目进行不同的修改就好.
自己做的demo效果