当前位置: 首页 > 编程日记 > 正文

Quartz2D在项目中的实际使用

还记得大学刚学iOS那会,从学校图书馆借了本iOS开发的书,有一章节介绍了Quartz2D,当时看得一头雾水,感觉这画画线,画画圆有什么用呢🤔️?工作一段时间后,遇到了一些需求,终于可以把咸丰年学的Quartz2D知识拿出来用一用了💪。下面总结下这些年做项目用到Quartz2D的7个例子。

一.单纯画个圈。

有个项目要模仿呆萌价APP顶部轮播图,然后轮播图后面需要有个圆弧:
在这里插入图片描述
一看到这需求,不简单吗?找UI小姐姐切个圆弧图片就好啦😄。
但是细细一看。wtf🙀。圆弧颜色是随着轮播图一起改变的:
在这里插入图片描述
在这里插入图片描述
也就是圆弧会根据录播图的主色调而改变颜色,或许我们可以麻烦UI小姐姐提供多个颜色的切图。但是这样只能是有限个颜色值了。而且图片多了。。。还增加了包大小🤣🤣。
此时只要用Quartz2D,简单几句代码就解决问题啦,寥寥十几行代码还几乎不增加包大小。

1.新建HYBgView,继承View
2.重写drawRect:方法
-(void)drawRect:(CGRect)rect{CGContextRef context = UIGraphicsGetCurrentContext();UIBezierPath *path = [UIBezierPath bezierPath];[path moveToPoint:CGPointMake(0, 0)];[path addLineToPoint:CGPointMake(0, 60)];[path addQuadCurveToPoint:CGPointMake(kScreenWidth, 60) controlPoint:CGPointMake(kScreenWidth*0.5, 120)];[path addLineToPoint:CGPointMake(kScreenWidth, 0)];[path closePath];CGContextAddPath(context, path.CGPath);CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:self.hyColor].CGColor);CGContextFillPath(context);
}

其中hyColor是我们定义的HYBgView的属性,类型为UIColor:

@interface HYBgView : UIView@property(nonatomic,strong) NSString *hyColor;@end
3.重写hyColor的set方法,在修改颜色时让系统进行重绘:
-(void)setHyColor:(NSString *)hyColor{_hyColor = hyColor;[self setNeedsDisplay];
}

二.带透明窗口的引导图

在老东家太平洋网络做的项目,如下图的一键海报的新手指引图,需求是遮罩层中间有个镂空的矩形,把第一张海报显示出来,其它地方是50%透明度,当时最终实现效果如图:
在这里插入图片描述
我们通过UIBezierPath和CAShapeLayer绘制一张中间镂空(完全透明),其它部分50%透明的遮罩层。

1、新建类PCOnePosterGuide,继承UIView
2、重写drawRect:方法:
- (void)drawRect:(CGRect)rect {[super drawRect:rect];//整个view(如下图,蓝色部分,为方便解释上的颜色,实际效果为50%透明,下同)UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:0];//中间空的部分(如下图:粉红色部分,实际效果为镂空透明)UIBezierPath *maskPath;CGFloat maskW = (IOS_VERSION>=10.)?64.:50.;CGFloat padding = (SCREEN_WIDTH>375)?6.:2.;maskPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(SCREEN_WIDTH-maskW-padding, PCSTATUSBAR_HEIGHT+4, maskW, 36.)byRoundingCorners:UIRectCornerAllCornerscornerRadii:CGSizeMake(2, 2)];[path appendPath:maskPath];//使用奇偶性原则,设置填充部分为除去粉色的蓝色部分[path setUsesEvenOddFillRule:YES];CAShapeLayer *fillLayer = [CAShapeLayer layer];fillLayer.path = path.CGPath;fillLayer.fillRule = kCAFillRuleEvenOdd;fillLayer.fillColor = [UIColor blackColor].CGColor;fillLayer.opacity = 0.5;[self.layer addSublayer:fillLayer];  
}

为了方便解释,上的颜色,实际为透明
在这里插入图片描述

三、排序按钮

如图中的排序按钮(正序/倒序),完全使用Core Graphic进行绘制,可以方便地设置颜色、大小、字体等,而不需要找设计同事拿切图哦😊:
在这里插入图片描述
在这里插入图片描述
绘制代码:

- (void)drawRect:(CGRect)rect {CGContextRef context = UIGraphicsGetCurrentContext();if (_title.length > 0) {//绘制文字CGSize textSize = [_title sizeForFont:[UIFont systemFontOfSize:14] size:CGSizeMake(200, 40) mode:NSLineBreakByClipping];CGFloat textW = textSize.width;CGFloat textH = textSize.height;UIColor *selectColor = self.selectColor?:[UIColor colorWithRed:137/255.0 green:67/255.0 blue:167/255.0 alpha:1.0];UIColor *unselectColor = self.unselectColor?:[UIColor colorWithRed:102/255.0 green:102/255.0 blue:102 /255.0 alpha:1.0];UIColor *textColor = self.type==HYRankTypeNone?unselectColor:selectColor;[_title drawInRect:CGRectMake((self.width-textW)/2.0, (self.height-textH)/2.0, textW, self.height) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14],NSForegroundColorAttributeName:textColor}];CGFloat triangleW = self.triangleW>0?self.triangleW:10;CGFloat trianglePadding = 4;//绘制上三角形if (self.type == HYRankTypeNone || self.type == HYRankTypeDown) {CGContextSetFillColorWithColor(context, unselectColor.CGColor);}else{CGContextSetFillColorWithColor(context, selectColor.CGColor);}CGFloat x1 = (self.width+textW)/2.0+trianglePadding+triangleW/2.0;CGFloat y1 = self.height/2.0 - triangleW/2.0 - 1;CGContextMoveToPoint(context, x1, y1);CGFloat x2 = x1+triangleW/2.0;CGFloat y2 = y1+triangleW/2.0;CGContextAddLineToPoint(context, x2, y2);CGFloat x3 = x1-triangleW/2.0;CGFloat y3 = y2;CGContextAddLineToPoint(context, x3, y3);CGContextClosePath(context);CGContextFillPath(context);//绘制下三角形if (self.type == HYRankTypeNone || self.type == HYRankTypeUp) {CGContextSetFillColorWithColor(context, unselectColor.CGColor);}else{CGContextSetFillColorWithColor(context, selectColor.CGColor);}CGFloat a1 = x1;CGFloat b1 = y1 + triangleW + 2;CGContextMoveToPoint(context, a1, b1);CGFloat a2 = x2;CGFloat b2 = y2 + 2;CGContextAddLineToPoint(context, a2, b2);CGFloat a3 = x3;CGFloat b3 = y3 + 2;CGContextAddLineToPoint(context, a3, b3);CGContextClosePath(context);CGContextFillPath(context);}
}

排序按钮我简单地封装到了HYRankView,完整代码及详细使用方法点我

4.继续画画:卡片背景

如图中的卡片背景,也是可以通过Quartz2D快速画出来,又为APP包大小立下功劳~
在这里插入图片描述
绘制代码:

- (void)drawRect:(CGRect)rect {[super drawRect:rect];CGContextRef context = UIGraphicsGetCurrentContext();//左边半圆UIBezierPath *leftPath = [UIBezierPath bezierPath];CGFloat y = 158;[leftPath addArcWithCenter:CGPointMake(0, y) radius:15 startAngle:3/2.0*M_PI endAngle:1/2.0*M_PI clockwise:YES];[leftPath closePath];CGContextAddPath(context, leftPath.CGPath);CGContextSetFillColorWithColor(context, UIColorHex(#F9F8FF).CGColor);CGContextFillPath(context);//右边半圆UIBezierPath *rightPath = [UIBezierPath bezierPath];CGFloat rightX = kScreenWidth-32;[rightPath addArcWithCenter:CGPointMake(rightX, y) radius:15 startAngle:3/2.0*M_PI endAngle:1/2.0*M_PI clockwise:NO];[rightPath closePath];CGContextAddPath(context, rightPath.CGPath);CGContextFillPath(context);//中间分割虚线CGContextMoveToPoint(context, 30, y);CGContextAddLineToPoint(context, kScreenWidth-32-30, y);CGContextSetLineWidth(context, 1);CGContextSetStrokeColorWithColor(context, UIColorHex(#666666).CGColor);CGFloat lengths[] = {3,3};CGContextSetLineDash(context, 0, lengths,2);CGContextDrawPath(context, kCGPathStroke);
}

5.贝塞尔曲线+动画

这个demo是业余模仿美人相机的,还没用到实际项目上。效果:
在这里插入图片描述
我的另一篇博客写的很详细了,这里就不再累赘:

贝塞尔曲线动画demo(仿美人相机效果)

6.环形进度条

如图。是设计姐姐给的下载进度设计图。
在这里插入图片描述
其实就只画两个圈,一个灰色的圆环和一个根据下载百分比动态变化的黄色圆环。代码:

-(void)drawRect:(CGRect)rect{CGContextRef ctx = UIGraphicsGetCurrentContext();//获取上下文CGContextSetLineWidth(ctx, _progressWidth); //设置线条宽度CGPoint center = CGPointMake(rect.size.width / 2, rect.size.height / 2);  //设置圆心位置CGFloat radius = (rect.size.width - 2 * _progressWidth) * 0.5;  //设置半径CGFloat startA = - M_PI_2;  //圆起点位置CGFloat endA = -M_PI_2 + M_PI * 2 * _progress;  //圆终点位置UIBezierPath *bgCirclePath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:2*M_PI clockwise:YES];[[UIColor lightGrayColor] setStroke];//设置描边颜色CGContextAddPath(ctx, bgCirclePath.CGPath);//把路径添加到上下文CGContextStrokePath(ctx);//渲染UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];[UIColorHex(#f3b132) setStroke];CGContextAddPath(ctx, path.CGPath);CGContextStrokePath(ctx);
}

在改变进度时,请求重新绘制:

-(void)setProgress:(float)progress
{_progress = progress;[self setNeedsDisplay];
}

七、长度动画

业余接的一个美术学院学生的iPad项目(iPad搜索“傣纸的故事”),需要动态展示一些物件的大小尺寸,也不用麻烦设计,直接Quartz2D+Core Animation搞掂。最终效果如下图:
在这里插入图片描述
核心代码:

1.画出完整的虚线
- (void)drawRect:(CGRect)rect {//获得处理的上下文CGContextRef context = UIGraphicsGetCurrentContext();//线条宽CGContextSetLineWidth(context, 2.0);//线条颜色CGContextSetStrokeColorWithColor(context, ColorForDardTheme.CGColor);//画虚线CGFloat dashArray[] = {3, 1};//表示先画3个实点再画1个虚点,即实点多虚点少表示虚线点大且间隔小,实点少虚点多表示虚线点小且间隔大CGContextSetLineDash(context, 1, dashArray, 1);//最后的参数1代表排列的个数//起点坐标CGContextMoveToPoint(context, 0, rect.size.height/2);//终点坐标CGContextAddLineToPoint(context, rect.size.width, rect.size.height/2);//绘制路径CGContextStrokePath(context);}
2.加一个遮罩动画就动起来啦
-(void)showAnimation:(HYPointLineDirect)direct{CGFloat originFrameX,endPositionX;switch (direct) {case HYPointLineDirectLeft:originFrameX = self.bounds.size.width;endPositionX = self.bounds.size.width/2;break;case HYPointLineDirectRight:originFrameX = -self.bounds.size.width;endPositionX = self.bounds.size.width/2;break;default:originFrameX = self.bounds.size.width;endPositionX = self.bounds.size.width/2;break;}UIView *maskView = [[UIView alloc] initWithFrame:CGRectMake(originFrameX, 0, self.frame.size.width, self.frame.size.height)];maskView.backgroundColor =  [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];[self setMaskView:maskView];CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"];animation.toValue = @(endPositionX);animation.duration = 1.0;animation.removedOnCompletion = NO;animation.fillMode = kCAFillModeBoth;[maskView.layer addAnimation:animation forKey:nil];
}

暂时就记得这几个例子。后面有再更新,
总结就是三步:
1.新建类继承UIView
2.重写drawRect:方法,在方法内画画
3.在需要刷新时调用setNeedsDisplay进行重绘

可怜的我辛苦敲代码之余还抽空写博客✍️,兄弟底部点个赞鼓励下再走嘛🥺~

相关文章:

区别:电感、磁珠和零欧电阻的作用

转载:http://www.cntronics.com/sensor-art/80022840 【导读】电感、磁珠和零欧电阻在电路中是常见的身影。对于这三者在电路中的作用及它们之间的区别,相信还有很多工程师不是很清楚。不过没关系,小编在此为大家奉上一篇关于电感、磁珠和零欧…

【转载】Linux下安装、配置、启动Apache

原文地址:http://www.cnblogs.com/zhuque/archive/2012/11/03/2763352.html 安装Apache前准备: 1、检查该环境中是否已经存在httpd服务的配置文件,默认存储路径:/etc/httpd/httpd.conf(这是centos预装的Apache的一个ent版本&#…

MIME格式解析

“ 本文介绍常见的MIME数据格式。”在协议还原中,不可避免地,经常会在各类协议内容中碰到MIME格式,例如标准邮件协议、HTTP协议。那么,什么是MIME呢?MIME是英文Multipurpose Internet Mail Extensions的缩写&#xff0…

AngularJs--过滤器(filter)

过滤器(filter)正如其名,作用就是接收一个输入,通过某个规则进行处理,然后返回处理后的结果。主要用在数据的格式化上,例如获取一个数组中的子集,对数组中的元素进行排序等。ng内置了一些过滤器…

【一步步学小程序】1.创建项目以及TabBar

1.创建项目 如图,创建项目,输入项目名称、选择目录,AppID是唯一标识,我们可以先点如图红框内的测试号,自动生成一个AppID,然后点新建即创建完一个新项目。 2.创建3个页面 确保如图左上角的编译器按钮是…

Yii在window下的安装方法

首先,在http://www.yiichina.com/上下载yii 然后,配置系统环境变量,在win8下,按winx,找到系统->高级系统设置->环境变量->path 把php的运行环境,加入到环境变量中,以分号隔开。如&…

从新手到入门,如何进入协议分析的世界

“ 协议分析与还原自学及入门指南。”有部分朋友给我发消息,说对协议还原很感兴趣,但苦于没人指导,希望得到我的帮助,问我如何进行协议分析的学习。这篇文章从初学者的角度,编列了一个学习指南,希望能对协议…

C# 学习笔记01

想写一个app可以访问数据库,实现对数据库的查询,修改等,突然发现知识实在有限,故选择C#来实现此app。 使用简单的三层架构来作为此app的架构。表现层(UI)、业务逻辑层(BLL)、数据访问…

转载 iOS js oc相互调用(JavaScriptCore) --iOS调用js

iOS js oc相互调用(JavaScriptCore) 从iOS7开始 苹果公布了JavaScriptCore.framework 它使得JS与OC的交互更加方便了。 下面我们就简单了解一下这个框架 首先我导入framework 方法如下 点击Linked Frameworks and Libraries 的添加后 选择 JavaScriptCor…

【一步步学小程序】2.列表展示

我们上一节已经创建了一个可以点击切换的tabbar。这节我们开始正式敲代码,在首页上展示一个可以上下滚动的课程列表: 首先打开上一节的pages/home/homeMain/homeMain.wxml文件,布局相关代码都会在此文件中,小程序的布局方式类似H…

git分支的合并

原文: http://gitbook.liuhui998.com/3_3.html http://gitbook.liuhui998.com/5_3.html 一、如何分支的合并在git中,可以使用git merge 和git rebase两个命令来进行分支的合并。git merge 和git rebase在大体上都差不多,下文主要以git merg…

【一步步学小程序】3. 使用自定义组件(component)

上一节创建了一个包含多个课程数据的列表。这一节我们用自定义组件(component),来优化列表页面,即如图,我们把每个课程单元格封装为组件。 使用组件的好处: 自定义组件可以在不同的页面中重复使用将复杂…

《lua程序设计(第二版)》学习笔记(五)-- 函数基础

-- 第 5 章 函数-- 一种对语句和表达式进行抽象的主要机制 print(os.date()); -- 打印日期 Sun Apr 20 12:44:46 2014 -- 一看到sun,感慨广州没有晴天 -- 函数没有参数也要括号 -- 特殊情况:只有一个参数的时候, 并且参数一个string/table构造…

HTTP协议中的chunked编码解析

“ HTTP协议中的chunked传输编码全接触。”在HTTP协议中,服务器发往客户端的数据中,通常都包括HTTP头和HTTP体,当存在HTTP体的时候,HTTP体的长度通常是由HTTP头内的“Content-Length”字段确定。就像下图:不过&#xf…

html-css实例

<!DOCTYPE html> <html><head><meta charset"utf-8" /><title>求签</title><style type"text/css">*{margin: 0px;padding: 0px;font-family: "微软雅黑",arial,sans-serif;}body{background: url(im…

【Swift】变量/常量/类型总结

1、变量&#xff08;Variable&#xff09; 变量&#xff0c;可以理解为存放某一类型的值的容器&#xff0c;如&#xff1a; var count:Int var shouldRemind:BOOL var text:String var list:[ChecklistItem]一个变量的数据类型&#xff0c;决定了它能存放什么类型的数据。有些…

ODBC更新记录集提示”记录集为只读“

创建的ODBC应用程序默认的记录集不具有只读属性&#xff0c;但是再更新记录表时会提示”记录集为只读“&#xff0c;这是为什么呢&#xff1f; 今天看书找到了答案&#xff1a; 因为MFC中的数据库类不支持需要连接两个或者多个表的记录集更新&#xff0c;如果选择数据源的时候选…

gzip格式分析与识别

“ 介绍gzip格式&#xff0c;识别gzip压缩的数据流量。”在协议分析过程中&#xff0c;经常会发现gzip压缩的数据&#xff0c;例如在HTTP协议中&#xff0c;在HTTP头中会标示&#xff0c;内容编码为gzip、DEFLATE。但是&#xff0c;还有很多情况&#xff0c;例如一些非HTTP协议…

CSS 和 JS 动画哪个更快

基于Javascript的动画暗中同CSS过渡效果一样&#xff0c;甚至更加快&#xff0c;这怎么可能呢&#xff1f;而Adobe和Google持续发布的富媒体移动网站的性能可媲美本地应用&#xff0c;这又怎么可能呢&#xff1f; 本文逐一遍览了基于Javascript的DOM动画库&#xff0c;如Veloci…

C语言之分支结构 if(一)

一 程序的三种基本结构 顺序结构&#xff1a;程序从上往下依次执行&#xff0c;这个叫顺序结构 分支结构&#xff1a;有选择的执行或者不执行某段代码 循环结构&#xff1a;重复的执行某段代码 二 分支结构之if 最简单的俩种用法 (tips: if语句后面的大括号可以省略&#xff1a…

react-native安装Ant Design

1.集成Ant Design到项目 项目根目录中执行命令&#xff1a; npm install ant-design/react-native --save2.集成按需加载babel-plugin-import到项目 项目根目录中执行命令&#xff1a; npm install --save-dev babel-plugin-import3.创建.babelrc文件 根目录中创建新文件…

车联网APP,安全设施薄弱的山寨品

“ 目前的车联网APP&#xff0c;几乎没有安全性可言。”在网络上闲逛&#xff0c;一不小心&#xff0c;逛进了车联网的领地。物联网、车联网、IoT如火如荼&#xff0c;各个大佬、院士加持&#xff0c;看着相当的高大上。但是&#xff0c;在伟岸的外表下&#xff0c;到底真实的情…

CSS里总算是有了一种简单的垂直居中布局的方法了

<!DOCTYPE html> <html xmlns"http://www.w3.org/1999/xhtml"> <head><meta http-equiv"Content-Type" content"text/html; charsetutf-8"/><title>无标题文档</title><style type"text/css"&…

【星榜单】盘点那些坑爹的国产手机们

【星榜单】盘点那些坑爹的国产手机们 国产手机的那些坑爹事儿很多&#xff0c;中庸到基本大众脸的设计还算是有点良心的&#xff0c;那些奇葩的名字、所谓的高配低价低却又山寨级的做工、饥饿营销让你看得到买不到、伪小清新却又华而不实放眼过去的国产智能手机比比皆是&#x…

App Tracking Transparency被拒解决

App Tracking Transparency 如果使用了App Tracking Transparency&#xff0c;苹果要求在iOS 14.5及以上的版本中必须在弹框取得用户同意后&#xff0c;才可以跟踪用户。否则会被拒&#xff1a; 解决方案 参照官方文档说明&#xff08;https://developer.apple.com/documen…

ProtoBuf格式详解

“介绍protobuf编码格式。”protobuf是一种数据交换格式&#xff0c;又称PB编码&#xff0c;由Google开源&#xff0c;类似于Json、XML&#xff0c;但其内部是纯二进制格式&#xff0c;比Json&#xff0c;XML等格式要更精炼&#xff0c;主要用于数据的序列化和反序列化&#xf…

Android studio 第二次作业

作业要求&#xff1a; 作一个显示框里面分成三行 一二行占这个框的1/2 第三行独占1/2 第三行里面分成两列第一列占25%&#xff0c;第二列占75%。 屏幕显示效果 实现步骤&#xff1a; <LinearLayout android:orientation"vertical"注意这里是横向布局 …

Cable master (POJ No.1064)

二分搜索思想&#xff1a;bool C(double x)可以得到长度为x的绳子//#define LOCAL #include<stdio.h> #include<math.h> int const MAX_N10005; int const MAX_M100; double const INF100000000; int N,K; double d[MAX_N],lb,ub; //判断是否满足条件 bool C(doubl…

iOS 11 导致tableview 刷新之后漂移问题

在10 系好好的&#xff0c;在11系统刷新只有就会多一个白块。查询才返现&#xff0c;添加一下代码 完美解决此bugself.mainTableView.estimatedRowHeight 0; self.mainTableView.estimatedSectionHeaderHeight 0; self.mainTableView.estimatedSectionFooterHeight 0;

HTTP协议解析之Cookie

“ Cookie与身份认证。”提到HTTP协议&#xff0c;不可避免地都会牵涉到Cookie&#xff0c;可以说&#xff0c;Cookie作为HTTP的重要组成部分&#xff0c;促进了HTTP协议的发展壮大。HTTP协议如果没有了Cookie&#xff0c;将会是一个无状态&#xff0c;无法便捷地进行用户识别的…