手写输入---随手写

news/2024/10/22 11:40:08/

手写输入—随手写
最近做的是关于教育的app,分老师版和学生版;学生版有做题功能,领导最近看到别的app里面有手写输入功能,保留原笔迹,也就是说写成什么样就是什么样,然后保存,上传。
思路1:
①上面排版的是collectionView
② 输入区域,根据UIView的touch事件,生成UIBezilPath。然后得到了path。layer.path = bezierPath.cgpath 。然后layer.stokeColor = xxxx
③ 最后layer加到item的某个view属性的layer上,调整下transform即可实现.aspectFit的效果
④ 当touch事件结束一段时间后(这个时间根据需求定),生成path走后面的渲染方法。
⑤但放到collectionView的item里,必须保证用一个transform让它们统一大小,并和item边缘相切。
思路2:
①上面排版的是textView
②输入区域,根据UIView的touch事件,生成UIBezilPath。然后得到了path。layer.path = bezierPath.cgpath 。然后layer.stokeColor = xxxx生成path走后面的渲染方法
③当touch事件结束一段时间后,对渲染部分截图(具体截多大的图,从什么位置截,demo里细讲),保存。
④利用textview的TextAttachment属性显示图片,bounds是设定图片大小,index是设定图片的位置
总结:
根绝需求分析,第一个思路不是太满足项目需求,因为领导要求是可以编辑,用collectionView就很麻烦,还要写光标,果断选择思路2
具体实现过程
先实现画板部分

//触摸点开始记录,一移动再记录,这样就记录无数多个点便成了线
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{if (self.beginEditingBlock) {self.beginEditingBlock();}[self.timer invalidate];self.timer = nil;self.seconds = 1;flag=NO;NSArray *array = [touches allObjects];for(UITouch *touch in array){Squiggle *squiggle = [[Squiggle alloc] init];[squiggle setLineWidth:lineWidth];[squiggle setStrokeColor:color];//self  指当前这次触摸事件[squiggle addPoint:[touch locationInView:self]];//因为每次触摸事件的 内存地址唯一,所以将其作为 squiggle的关键字key//将内存地址转换为对象NSValue *touchValue = [NSValue valueWithPointer:(__bridge const void * _Nullable)(touch)];NSString *key = [NSString stringWithFormat:@"%@",touchValue];[squigglesDic setValue:squiggle forKey:key];}
}-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{if (self.beginPaintBlock) {self.beginPaintBlock();}[self.timer invalidate];self.timer = nil;self.seconds = 1;self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeAnim) userInfo:nil repeats:YES];flag=YES;NSArray *array = [touches allObjects];for(UITouch *touch in array){//这里因为在前面 touchBegan中已经存好了相应的key,每一次触摸都有一关键字对应,这里只是在触摸的基础上移动画点NSValue *touchValue = [NSValue valueWithPointer:(__bridge const void * _Nullable)(touch)];Squiggle *squiggle = [squigglesDicvalueForKey:[NSString stringWithFormat:@"%@",touchValue]];CGPoint current = [touch locationInView:self];CGPoint previous = [touch previousLocationInView:self];//一直将当前点加进pointsArray中[squiggle addPoint:current];//更新后,得声明重新执行下 drawRect方法,系统不会自动执行CGPoint lower,higher;lower.x = (previous.x > current.x ? current.x : previous.x);lower.y = (previous.y > current.y ? current.y : previous.y);higher.x = (previous.x < current.x ? current.x : previous.x);higher.y = (previous.y < current.y ? current.y : previous.y);// redraw the screen in the required region[self setNeedsDisplayInRect:CGRectMake(lower.x-lineWidth,lower.y-lineWidth, higher.x - lower.x + lineWidth*2,higher.y - lower.y + lineWidth * 2)];}
}
保存图片
-(void)endFinish
{NSMutableArray *arr = _painterView.finishSquiggles;CGFloat minX = 0.0;CGFloat minY = 0.0;CGFloat maxX = 0.0;CGFloat maxY = 0.0;NSInteger index = 0;for(Squiggle *squiggle in arr){for (int i = 0; i<squiggle.pointsXArray.count; i++) {CGFloat x = [squiggle.pointsXArray[i] floatValue];CGFloat y = [squiggle.pointsYArray[i] floatValue];index++;if (index==1) {minX = x;maxX = x;minY = y;maxY = y;}else{if (x<minX) {minX = x;}if (x>maxX) {maxX = x;}if (y<minY) {minY = y;}if (y>maxY) {maxY = y;}}}}[pintArray addObject:[_painterView screenshot]];UIImage *image = [_painterView screenshotWithRect:CGRectMake(minX-2, minY-2, maxX-minX+4, maxY-minY+4)];CGFloat scale = image.size.width/image.size.height;UIImage *resultImage;NSInteger mMaxW = 42;NSInteger mMaxH = 40;if (image.size.height>mMaxH||image.size.width>mMaxW) {CGFloat imageW = 0;CGFloat imageH = 0;if (image.size.width>mMaxW) {if (image.size.height>mMaxH) {imageH = mMaxH;imageW = imageH*scale;CGSize size = CGSizeMake(imageW, imageH);//                    UIGraphicsBeginImageContext(size);UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);[image drawInRect:CGRectMake(0, 0, size.width, size.height)];resultImage= UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();}else{imageW = mMaxW;imageH = mMaxW/scale;CGSize size = CGSizeMake(imageW, imageH);//                    UIGraphicsBeginImageContext(size);UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);[image drawInRect:CGRectMake(0, 0, size.width, size.height)];resultImage= UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();}}else{if (image.size.height>mMaxH) {imageH = mMaxH;imageW = imageH*scale;CGSize size = CGSizeMake(imageW, imageH);//                    UIGraphicsBeginImageContext(size);UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);[image drawInRect:CGRectMake(0, 0, size.width, size.height)];resultImage= UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();}else{resultImage = image;}}}else{resultImage = image;}[pintArray addObject:resultImage];[_painterView resetView];NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithAttributedString:contentTextView.attributedText];NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithData:nil ofType:nil] ;textAttachment.image = resultImage; //要添加的图片NSAttributedString *textAttachmentString = [NSAttributedString attributedStringWithAttachment:textAttachment] ;CGFloat location = contentTextView.selectedRange.location;[string insertAttributedString:textAttachmentString atIndex:(NSUInteger)location];//index为用户指定要插入图片的位置contentTextView.attributedText = string;contentTextView.selectedRange = NSMakeRange(location+1, 0);
}

编辑
-(void)clickMenuButton:(UIButton *)sender
{
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithAttributedString:contentTextView.attributedText];
CGFloat location = contentTextView.selectedRange.location;

if (sender.tag==0) {//空格[string insertAttributedString:[[NSAttributedString alloc]initWithString:@" "] atIndex:(NSInteger)location];contentTextView.attributedText = string;contentTextView.selectedRange = NSMakeRange(location+1, 0);
}else if (sender.tag==1){//换行[string insertAttributedString:[[NSAttributedString alloc]initWithString:@"\n"] atIndex:(NSInteger)location];contentTextView.attributedText = string;contentTextView.selectedRange = NSMakeRange(location+@"\n".length, 0);
}else{//删除if (location<1) {return;}NSAttributedString *mu1 = [string attributedSubstringFromRange:NSMakeRange(0, location-1)];NSAttributedString *mu2 = [string attributedSubstringFromRange:NSMakeRange(location, string.length-location)];if (mu2.length==0) {mu2 = [[NSAttributedString alloc]initWithString:@""];}NSMutableAttributedString *muAtt = [[NSMutableAttributedString alloc]initWithAttributedString:mu1];[muAtt appendAttributedString:mu2];contentTextView.attributedText = [[NSAttributedString alloc]initWithAttributedString:muAtt];if (location>0) {contentTextView.selectedRange = NSMakeRange(location-1, 0);}else{contentTextView.selectedRange = NSMakeRange(0, 0);}
}
[self beginPaint];

}

demo放在GitHub上了记得Star 、 Fork


http://www.ppmy.cn/news/695519.html

相关文章

手写apply

在自己实现apply之前&#xff0c;我们需要先了解一下对函数使用了apply之后完成了那些效果&#xff0c;再考虑怎么自己编写代码去实现这些效果。 let name "张三" let personObj {name: "李四", } function getPersonName(){console.log(this)console.lo…

中文手写输入 (一)

最近业余时间在学习android的系统&#xff0c;想尝试将中文手写输入支持加到android上去&#xff0c;将最近的学习结果记录下来。 先上个截图: [img]/upload/attachment/56882/6bec42ff-5f30-3a2b-8baf-cc5030009305.png[/img] 你可以在线测试&#xff1a; [url]http://quake.…

如何在Windows 10上使用手写输入

Windows 10’s handwriting keyboard allows you to enter text into any application with a pen or other stylus. It even works on old desktop applications. Windows 10的手写键盘允许您使用笔或其他手写笔在任何应用程序中输入文本。 它甚至可以在旧的桌面应用程序上运行…

Go 接口声明

Go 语言中的接口是一种非常强大的特性&#xff0c;它允许我们定义一组方法&#xff0c;然后将其绑定到不同的数据类型上。本文将详细介绍 Go 语言中接口的声明、实现和使用方法&#xff0c;包括接口的定义、接口实现、接口类型断言等方面。 接口的定义 在 Go 语言中&#xff…

系列二、RocketMQ基本概念 系统架构

一、基本概念 1.1、消息&#xff08;Message&#xff09; 消息是指&#xff0c;消息系统所传输信息的物理载体&#xff0c;生产和消费数据的最小单位&#xff0c;每条消息必须输入一个主题。 1.2、主题&#xff08;Topic&#xff09; Topic表示一类消息的集合&#xff0c;每个…

使用鲁大师检测旧电脑信息如下:

电脑概览信息&#xff1a;电脑型号 惠普 康柏14 Notebook PC 笔记本电脑 (扫描时间&#xff1a;2018年04月24日)操作系统 Windows 10 专业版 64位 ( DirectX 12 )处理器 英特尔 第四代酷睿 i5-4200M 2.50GHz 双核主板 惠普 225B ( 英特尔 Haswell - Lynx Point )内存 4 GB ( 威…

vmware VM虚拟机去虚拟化教程 硬件虚拟机 过鲁大师检测

一 准备工作 1. 这里演示的VM虚拟机版本是12.5.9 虚拟机系统是win7 64位 2. 用到的工具 winhex和Phoenix BIOS Editor 下载地址工具 链接&#xff1a;https://pan.baidu.com/s/1b3FfA3FyQ_lnFQSjpCGLGg?pwd1221 提取码&#xff1a;1221 3. 注意&#…

系统自带测试软件,无需鲁大师检测!Windows自带工具检查系统健康度

前段时间的单位体检,小编的结果那真是惨不忍睹,眼睛已瞎、颈椎要废、器官也都快成石榴了,平常用的太狠,现在明显扛不住了。天天伴随大家休闲、工作的电脑也是如此,经过了1年的折腾,软硬件的健康度也在直线下降中。懒得重装系统的家伙们肯定会用第三方检测、清理、修复程序…