UIBezierPath是对Core Graphics框架的一种上层封装,目的是让绘图需求可以被更方便的使用。
那你有没有发现被UIBezierPath封装后与之前有什么改变?
答:有三个变化。
1.屏蔽繁杂重复的内容
2.功能阉割
3.坐标系顺时针方向反转
 
证明1:屏蔽繁杂重复的内容
相比Core Graphics框架,UIBezierPath帮我们做了一些繁琐的事件。比如有这样一个场景:需要画一个圆,但是它的每个1/4弧线的strokpath颜色是不同的。对于这样的需求。
有个错误的做法是:
1.拿到上下文
2.设置第一个1/4户的strokpath颜色,用上下文绘制第一个1/4弧
3.设置第一个2/4户的strokpath颜色,用上下文绘制第一个2/4弧
4.设置第一个3/4户的strokpath颜色,用上下文绘制第一个3/4弧
5.设置第一个4/4户的strokpath颜色,用上下文绘制第一个4/4弧
最后的结果会发现,这四段弧的颜色是最后一个4/4弧的strokpath的颜色
原因是:对于一个上下文来说,strokPathColor属性只有一个,虽然设置了4次,但总是后面的覆盖前面的。
 
一种解决方法是:
在第2步之前,先循环4次操作
let content = UIGraphicsGetCurrentContext()
content?.setStrokeColor(UIColor.blue.cgColor)
content?.saveGState()
然后在每一步绘制前,恢复上下文栈中的存储到当前上下文

content?.restoreGState()
另一种解决方法是:
直接创建4个UIBezierPath,用贝塞尔曲线绘制着4段弧。
这样就很直观的看出,每个UIBezierPath的上下文都是独立的。内部帮我们自己做了上下文的存栈和出栈。
 
证明2:功能阉割
虽然有了UIBezierPath的封装我们用起来方便了,但是相应的代价是所提供的功能被阉割了。有些强大的功能UIBezierPath没有提供实现,比如:现在要画一个圆形的渐变球,就只能使用Core Graphics框架。
代码如下
//利用上下文绘制渐变色(圆形)
let context = UIGraphicsGetCurrentContext()
//颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
let startColor = UIColor.black
let endColor = UIColor.red
//颜色数组
let colors = [startColor.cgColor,endColor.cgColor]
//颜色所处位置
let locations:[CGFloat] = [,]
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as! CFArray, locations: locations)
let center = CGPoint(x: rect.size.width*0.5, y: rect.size.height*0.5)
let radius = rect.size.height*0.3
context?.drawRadialGradient(gradient!, startCenter: center, startRadius: radius*0.2, endCenter: center, endRadius: radius, options: CGGradientDrawingOptions.drawsBeforeStartLocation)
证明3:坐标系顺时针方向反转
你知道吗, CoreGraphics绘图系统和Bezier贝塞尔曲线坐标系的顺时针方向是相反的!
 
我记得上学时老师讲的坐标系是这样的: 

X轴指向右侧,Y轴指向上面。对应的弧度如图上标的那样。顺时针也是钟表表针转动的方向。这就是最早接触的坐标系,熟悉的单纯模样。

在工作时,当我们往屏幕上布局UI时,用到的坐标系是下面这样:

对于UI控件来讲的坐标系模式,X轴方向向右,Y轴方向向下。
请注意弧度值也相应的转了方向,它是沿着X,Y指向的方向开始逐渐增加的。
顺时针还是熟悉的钟表表针转动方向。
 
关键代码如下:
        let content = UIGraphicsGetCurrentContext()

        var endAngl = _progressValue*CGFloat(M_PI*)
var clockState = (_direction == .onTime) //圆
var des: String = ""
des = clockState ? "UIGraphics上下文绘制、顺时针" : "UIGraphics上下文绘制、逆时针” content?.move(to: CGPoint(x: width-arcRadius, y: height*0.5))
let bez = UIBezierPath(arcCenter: arcCenter, radius: arcRadius, startAngle: , endAngle: endAngl, clockwise: clockState)
content?.addPath(bez.cgPath) NSString(string: des).draw(in: CGRect(x: , y: , width: width*0.4, height: height*0.5), withAttributes: atts)
log = String(format: "绘制弧度: %.4f Pi", endAngl/3.14) content?.strokePath()

实际效果图如下:

UIBezierPath顺时针模式下,从0到2PI的效果
 
UIBezierPath逆时针模式下,从0到2PI的效果
然后突出的CoreGraphics表示不服,我就要与众不同。如下图:

说出来你可能不信,你会发现顺时针方向往上了。这明明是逆时针方向啊!WTF?

来看下代码和实现效果吧。

       let content = UIGraphicsGetCurrentContext()

        var endAngl = _progressValue*CGFloat(M_PI*2)
var clockState = (_direction == .onTime) //圆
var des: String = ""
des = clockState ? "UIGraphics上下文绘制、顺时针" : "UIGraphics上下文绘制、逆时针” content?.move(to: CGPoint(x: width-arcRadius, y: height*0.5))
content?.addArc(center: arcCenter, radius: arcRadius, startAngle: 0, endAngle: endAngl, clockwise: clockState) NSString(string: des).draw(in: CGRect(x: 2, y: 2, width: width*0.4, height: height*0.5), withAttributes: atts)
log = String(format: "绘制弧度: %.4f Pi", endAngl/3.14) content?.strokePath()

实际效果如下:

CoreGraphics顺时针模式下,从0到2PI的效果

CoreGraphics逆时针模式下,从0到2PI的效果

CoreGraphics和Bezier贝塞尔曲线都是平时开发中的利器,认真品味一下两者的区别,会让我们对它们有更深的认识。

有讲的不对的地方欢迎指正。

Demo地址:https://github.com/zhfei/CoordinateSystem

你知道吗, CoreGraphics绘图系统和Bezier贝塞尔曲线坐标系的顺时针方向是相反的!的更多相关文章

  1. 下一代大数据系统和4S标准

    大数据行业发展到今天,它创造的价值和带来的社会效应,大家已经看得很明白,同时很多问题和不足也暴露出来,特别是hadoop能够提供的数据处理能力,现在已经挖掘到极限,但是现在各行业对数据的存储和计算需求 ...

  2. 操作系统和Python的发展历程

    一:操作系统的发展历史: 操作系统:什么是操作系统?我们首先想到的是电脑,,也就是所谓的Windows8,Windows7,或者XP系统和Windows10,当然也包括我们手机的安卓系统或者IPhon ...

  3. 使用拷贝的方式(adb push) 绕过Android系统和adb install直接安装APK

    某些情况下定制的Android系统为了限制用户安装应用,例如电视盒子,车载中控等,通过修改代码屏蔽了正常安装应用的方式 本文探讨如何在 adb shell 具有读写data分区目录的权限前提下,通过a ...

  4. GNU构建系统和AutoTools

    注:本篇博客是阅读文末[参考博客]的讲解所写,内容非原创,仅是学习笔记 1. 概述2. 不同视角的程序构建2.1 用户视角2.2 开发者视角3. 导图图片4. configure选项参考博客 1. 概 ...

  5. android系统和ios系统是如何实现推送的,ios为什么没有后台推送

    ios系统为什么没有后台推送? iOS 为了真正地为用户体验负责,不允许应用在后台活动.有了这个限制,但是对于终端设备,应用又是有必要“通知”到达用户的,随时与用户主动沟通起来的(典型的如聊天应用). ...

  6. gpio子系统和pinctrl子系统(下)

    情景分析 打算从两个角度来情景分析,先从bsp驱动工程师的角度,然后是驱动工程师的角度,下面以三星s3c6410 Pinctrl-samsung.c为例看看pinctrl输入参数的初始化过程(最开始的 ...

  7. gpio子系统和pinctrl子系统(上)

    前言 随着内核的发展,linux驱动框架在不断的变化.很早很早以前,出现了gpio子系统,后来又出现了pinctrl子系统.在网上很难看到一篇讲解这类子系统的文章.就拿gpio操作来说吧,很多时候都是 ...

  8. 一种基于uCos-II操作系统和lwIP协议栈的IEEE-1588主站以及基于该主站的报文处理方法

    主站以及应用于电力系统的支持IEEE‐1588协议的主时钟(IEEE‐1588主站)的实现方法.该方法是在一个低成本的硬件平台上,借助uCos‐II操作系统和TCP/IP的协议栈,对以太网数据进行了分 ...

  9. 基于GPS北斗卫星授时系统和NTP网络授时服务器的设计与开发

    基于GPS北斗卫星授时系统和NTP网络授时服务器的设计与开发 安徽京准科技提供@请勿转载@@ 更多资料请参考——ahjzsz.com 天文观测设备对于控制系统的时间准确度有严格要求.为此,采用搭建高精 ...

随机推荐

  1. UWP开发入门(三)——{x:Bind}扩展标记

    上周打炉石打得太晚……忘记更新了,本周补上.本篇我们讲一下{x:Bind}扩展标记.{x:Bind}扩展标记也是Windows 10 Uinversal 新增的内容,按官方的说法是 {Binding} ...

  2. c语言博客作业01—分支、顺序结构

    1.本章学习总结  1.1 思维导图  1.2本章学习体会及代码量学习体会  1.2.1学习体会 这周 对c语言的学习 明显与其他同学相比较有些滞后,觉得很大原因是暑假没有看教学视频,课前没有预习课本 ...

  3. 【Oracle 12c】CUUG OCP认证071考试原题解析(32)

    32.choose the best answer View the Exhibit and examine the data in EMP and DEPT tables. In the DEPT ...

  4. css3半圆

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. kvm虚拟化存储池配置

    1.创建基于文件夹的存储池(目录) 2.定义存储池与其目录 # virsh pool-define-as vmdisk --type dir --target /data/vmfs 3.创建已定义的存 ...

  6. php-fpm 和 nginx 的两种通信方式

    在 linux 中,nginx 服务器和 php-fpm 可以通过 tcp socket 和 unix socket 两种方式实现. 一下内容转自:https://blog.csdn.net/qq62 ...

  7. Security-OAuth2.0 密码模式之服务端实现

    第一步:配置数据库 ,固定创建三张表 ,OAuth2 框架需要默认使用这三张表 我使用的时Mysql,工具为navcat CREATE TABLE `oauth_access_token` ( `to ...

  8. C语言多线程编程二

    一. 线程通信----事件: 1.一对一模式: #include <stdio.h> #include <stdlib.h> #include <Windows.h> ...

  9. Ionic2 自学须知的基本知识点

    http://www.cnblogs.com/zsl123/p/5991336.html Ionic(ionicframework)一款接近原生的HTML5移动App开发框架. IONIC 是目前最有 ...

  10. Spark累加器

    spark累计器 因为task的执行是在多个Executor中执行,所以会出现计算总量的时候,每个Executor只会计算部分数据,不能全局计算. 累计器是可以实现在全局中进行累加计数. 注意: 累加 ...