iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >iOS新增绘制圆的方法实例代码
  • 576
分享到

iOS新增绘制圆的方法实例代码

ios绘制 2022-06-01 14:06:43 576人浏览 安东尼
摘要

iOS 的坐标系和我们几何课本中的二维坐标系并不一样! # BezierPath绘制圆弧 使用 UIBezierPath 进行绘制圆弧的方法,通常会直接使用 addArc : a

iOS 的坐标系和我们几何课本中的二维坐标系并不一样!

# BezierPath绘制圆弧

使用 UIBezierPath 进行绘制圆弧的方法,通常会直接使用 addArc :


addArc(withCenter:, radius:, startAngle:, endAngle:, clockwise:)

或者使用 addCurve 进行拟圆弧:


addCurve(to:, controlPoint1:, controlPoint2:)

其实我们可以通过,两个坐标点(startPoint & endPoint),和两点间的线段对应的圆弧的弧度(angle/radian)就能确定这个圆的信息(半径radius, center), 所以我们是不是可以封装出只提供 start, end 和 angle 就能绘制 arc 的函数?


addArc(startPoint: , endPoint: , angle: , clockwise:)

# 计算两点间的距离

这里逻辑很简单不做赘述。


func calculateLineLength(_ point1: CGPoint, _ point2: CGPoint) -> CGFloat {
  let w = point1.x - point2.x
  let h = point1.y - point2.y
  return sqrt(w * w + h * h)
}

# 计算两点间的夹角

计算 point 和 origin 连线在 ioS 坐标系的角度


func calculateAngle(point: CGPoint, origin: CGPoint) -> Double {
  
  if point.y == origin.y {
    return point.x > origin.x ? 0.0 : -Double.pi
  }
  
  if point.x == origin.x {
    return point.y > origin.y ? Double.pi * 0.5 : Double.pi * -0.5
  }
  // Note: 修正标准坐标系角度到 iOS 坐标系
  let rotationAdjustment = Double.pi * 0.5
  
  let offsetX = point.x - origin.x
  let offsetY = point.y - origin.y
  // Note: 使用 -offsetY 是因为 iOS 坐标系与标准坐标系的区别
  if offsetY > 0 {
    return Double(atan(offsetX / -offsetY)) + rotationAdjustment
  } else {
    return Double(atan(offsetX / -offsetY)) - rotationAdjustment
  }
}

# 计算圆心的坐标

如果你已经将几何知识丢的差不多了的话,我在这里画了个大概的草图,如下( angle 比较小时):

angle 比较大时:

所以我么可以写出如下计算中心点的代码


// Woring: 只计算从start到end **顺时针** 计算对应的 **小于π** 圆弧对应的圆心
// Note: 计算逆时针(end到start)可以看做将传入的start和end对调后计算顺时针时的圆心位置
// Note: 计算大于π的叫相当于将end和start对换后计算2π-angle的顺时针圆心位置
// Note: 综上传入start,end,angle 右外部自行处理逻辑
func calculateCenterFor(startPoint start: CGPoint, endPoint end: CGPoint, radian: Double) -> CGPoint {
  guard radian <= Double.pi else {
    fatalError("Does not support radian calculations greater than π!")
  }
  
  guard start != end else {
    fatalError("Start position and end position cannot be equal!")
  }
  
  if radian == Double.pi {
    let centerX = (end.x - start.x) * 0.5 + start.x
    let centerY = (end.y - start.y) * 0.5 + start.y
    return CGPoint(x: centerX, y: centerY)
  }
  
  let lineAB = calculateLineLength(start, end)
  
  // 平行 Y 轴
  if start.x == end.x {
    let centerY = (end.y - start.y) * 0.5 + start.y
    let tanResult = CGFloat(tan(radian * 0.5))
    let offsetX = lineAB * 0.5 / tanResult
    let centerX = start.x + offsetX * (start.y > end.y ? 1.0 : -1.0)
    return CGPoint(x: centerX, y: centerY)
  }
  
  // 平行 X 轴
  if start.y == end.y {
    let centerX = (end.x - start.x) * 0.5 + start.x
    let tanResult = CGFloat(tan(radian * 0.5))
    let offsetY = lineAB * 0.5 / tanResult
    let centerY = start.y + offsetY * (start.x < end.x ? 1.0 : -1.0)
    return CGPoint(x: centerX, y: centerY)
  }
  
  // 普通情况
  
  // 计算半径
  let radius = lineAB * 0.5 / CGFloat(sin(radian * 0.5))
  // 计算与 Y 轴的夹角
  let angleToYAxis = atan(abs(start.x - end.x) / abs(start.y - end.y))
  let cacluteAngle = CGFloat(Double.pi - radian) * 0.5 - angleToYAxis
  // 偏移量
  let offsetX = radius * sin(cacluteAngle)
  let offsetY = radius * cos(cacluteAngle)
  
  var centetX = end.x
  var centerY = end.y
  // 以 start 为原点判断象限区间(iOS坐标系)
  if end.x > start.x && end.y < start.y {
    // 第一象限
    centetX = end.x + offsetX
    centerY = end.y + offsetY
  } else if end.x > start.x && end.y > start.y {
    // 第二象限
    centetX = start.x - offsetX
    centerY = start.y + offsetY
  } else if end.x < start.x && end.y > start.y {
    // 第三象限
    centetX = end.x - offsetX
    centerY = end.y - offsetY
  } else if end.x < start.x && end.y < start.y {
    // 第四象限
    centetX = start.x + offsetX
    centerY = start.y - offsetY
  }
  
  return CGPoint(x: centetX, y: centerY)
}

这里附上一个逆时针绘制第一张图中圆心位置的草图,图中已将 start 和 end 对换

如果你对其中计算时到底该使用 + 还是 - 有困惑的话也可以自己多画些草图大概验证下,总之有疑惑多动手🤭

# 实现我们的目标函数

在有了计算圆心位置,和两点间角度的函数后我们很容易就能实现 addArc(startPoint: , endPoint: , angle: , clockwise:) 了;


func addArc(startPoint start: CGPoint, endPoint end: CGPoint, angle: Double, clockwise: Bool) {
  
  guard start != end && (angle >= 0 && angle <= 2 * Double.pi) else {
    return
  }
  if angle == 0 {
    move(to: start)
    addLine(to: end)
    return
  }
  
  var tmpStart = start, tmpEnd = end, tmpAngle = angle
  // Note: 保证计算圆心时是从 start 到 end 顺时针 小于 π 的角
  if tmpAngle > Double.pi {
    tmpAngle = 2 * Double.pi - tmpAngle
    (tmpStart, tmpEnd) = (tmpEnd, tmpStart)
  }
  if !clockwise {
    (tmpStart, tmpEnd) = (tmpEnd, tmpStart)
  }
  
  let center = calculateCenterFor(startPoint: tmpStart, endPoint: tmpEnd, radian: tmpAngle)
  let radius = calculateLineLength(start, center)
  
  var startAngle = calculateAngle(point: start, origin: center)
  var endAngle = calculateAngle(point: end, origin: center)
  // Note: 逆时针绘制则交换 startAngle 和 endAngle,并且将开始点移动的 end 位置
  if !clockwise {
    (startAngle, endAngle) = (endAngle, startAngle)
    move(to: end)
  }
  
  addArc(withCenter: center, radius: radius, startAngle: CGFloat(startAngle), endAngle: CGFloat(endAngle), clockwise: true)
  move(to: end)
}

# 完结

最后也不知道是你否会碰到相同的需求,这里附上源码和一份样例及运行结果图;


override func draw(_ rect: CGRect) {
  
  let path = UIBezierPath()
  var start = CGPoint(x: 160, y: 130)
  var end = CGPoint(x: 180, y: 200)
  path.move(to: start)
  path.addArc(startPoint: start, endPoint: end, angle: Double.pi * 1.6, clockwise: true)
  path.move(to: start)
  path.addArc(startPoint: start, endPoint: end, angle: Double.pi * 0.8, clockwise: true)
  
  start = CGPoint(x: 142, y: 130)
  end = CGPoint(x: 162, y: 200)
  path.move(to: start)
  path.addArc(startPoint: start, endPoint: end, angle: Double.pi * 0.4, clockwise: true)
  
  start = CGPoint(x: 140, y: 130)
  end = CGPoint(x: 160, y: 200)
  path.move(to: start)
  path.addArc(startPoint: start, endPoint: end, angle: Double.pi * 1.6, clockwise: false)
  path.move(to: start)
  path.addArc(startPoint: start, endPoint: end, angle: Double.pi * 0.8, clockwise: false)
  
  path.close()
  path.lineWidth = 1
  UIColor.red.setStroke()
  path.stroke()
}

ps: 每次都写 Double.pi / x 很烦? 试试类似于 SwiftUI 提供的接口, 使用 度数(degress) 而非 弧度(radian)


struct Angle {
  private var degress: Double
  static func deggess(_ degress: Double) -> Angle {
    return .init(degress: degress)
  }
  // 弧度
  var radians: Double { Double.pi * degress / 180.0 }
}

// Angle.deggess(90).radians // 1.570796326794897

func addArc(startPoint start: CGPoint, endPoint end: CGPoint, angle: Angle, clockwise: Bool)

感谢阅读,祝好祝顺🥰

总结

到此这篇关于iOS新增绘制圆的文章就介绍到这了,更多相关iOS新增绘制圆内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: iOS新增绘制圆的方法实例代码

本文链接: https://www.lsjlt.com/news/30443.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • OpenCV 绘制同心圆的示例代码
    目录功能函数测试代码最近在学习OpenCV,本文主要介绍了OpenCV 绘制同心圆的示例代码,分享给大家,具体如下: 功能函数 // 绘制同心圆 void DrawConcent...
    99+
    2024-04-02
  • OpenCV绘制圆角矩形的方法实例
    功能函数 // 绘制圆角矩形 void DrawRotatedRectChamfer(cv::Mat mask,const cv::RotatedRect rotatedrect...
    99+
    2024-04-02
  • OpenCV绘制圆端矩形的示例代码
    目录功能函数测试代码测试效果本文主要介绍了OpenCV绘制圆端矩形的示例代码,分享给大家,具体如下: 功能函数 // 绘制圆端矩形(药丸状,pill) void DrawPill...
    99+
    2024-04-02
  • 利用Pygame绘制圆环的示例代码
    目录三角函数弧度和角度的关系基本包和事件捕捉主程序全部代码三角函数 如果我们以OP作为圆的半径r,以o点作为圆的圆心,圆上的点的x坐标就是r * cos a ,y坐标就是 r * ...
    99+
    2024-04-02
  • Android绘制验证码的实例代码
    在前面仿华为加载动画、仿网易音乐听歌识曲-麦克风动画中,我们通过绘图的基础知识完成了简单的绘制。在本例中,我们将绘制常见的验证码。一、效果图二、知识点与思路分析通过上面的效果图观察,我们可以看到里面有绘制的随机线条,随机绘制的验证码。绘制线...
    99+
    2023-05-31
    android 验证码 roi
  • android屏幕圆角实现方法的示例代码
    现在很多全面屏手机的屏幕四角做成圆的,其圆润的感觉给人带来别样的视觉体验。先来一张我大锤子镇楼(不是广告呀,锤子没给钱),大家来直观感受一下圆角的魅力。锤子.jpg当然这种是硬件上实现的,我怀疑也是方的显示屏,然后做了个圆角遮蔽。那对于我们...
    99+
    2023-05-30
    android 屏幕 圆角
  • 利用JavaScript实现绘制2023新年烟花的示例代码
    目录前言烟花效果展示使用教程查看源码HTML代码CSS代码JavaScript新年祝福前言 大家过年好!新春佳节,在这个充满喜悦的日子里,愿新年的钟声带给你一份希望和期待,我相信,时...
    99+
    2023-01-28
    JavaScript绘制新年烟花 JavaScript新年烟花 JavaScript烟花
  • Python matplotlib绘制散点图的实例代码
    前言 前面说到的主要是matplotlib对于图像的基础操作,然后从这篇开始,主要说一下点图,分析点图在实际问题的数据处理中应用非常广泛,比如说逻辑回归是利用现有的数据点通过拟合得到...
    99+
    2024-04-02
  • C#实现绘制鼠标的示例代码
    目录实践过程效果代码实践过程 效果 代码 public partial class Form1 : Form { public Form1() ...
    99+
    2022-12-23
    C#绘制鼠标 C# 鼠标
  • Android实现绘制LocationMarkerView图的示例代码
    目录LocationMarkerView图的绘制绘制整公里的文字添加动画LocationMarker是运动轨迹上Start、End, 以及整公里点上笔者自定义绘制的一个MarkerV...
    99+
    2023-02-10
    Android绘制LocationMarkerView图 Android LocationMarkerView图 Android LocationMarkerView
  • Python实现绘制凸包的示例代码
    目录ConvexHullQG三维情况ConvexHull属性ConvexHull ConvexHull是spatial中的一个类,主要功能是找到一组点的边缘,并做一个凸包。其必要的初...
    99+
    2023-05-18
    Python绘制凸包 Python 凸包
  • html5 canvas绘制矩形和圆形的代码怎么写
    本篇内容介绍了“html5 canvas绘制矩形和圆形的代码怎么写”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有...
    99+
    2024-04-02
  • Python绘制灯笼的示例代码
    目录一、效果展示二、代码展示三、拓展一年一度的元宵节刚刚过去,由于时间关系,在元宵节当天晚上11点多才完成本文灯笼的绘制。这两天又在忙着别的事情,所以现在才跟大家分享。 一、效果展示...
    99+
    2024-04-02
  • Matlab实现绘制玫瑰线的示例代码
    目录绘制效果基础代码土味代码绘制效果 实际上就是在进行曲线: 的可视化,代码非常简单哈: 基础代码 function roseCurve1 set(gcf,'position'...
    99+
    2024-04-02
  • WPF实现绘制3D图形的示例代码
    目录关键概念视口相机光源材质3D对象命中测试(鼠标交互)3D对象中2D控件渲染外部导入3D模型WPF的3D功能可以在不编写任何c#代码的情况下进行绘制,只需要使用xaml即可完成3D...
    99+
    2023-03-02
    WPF绘制3D图形 WPF 3D图形 WPF 3D
  • Python绘制时钟的示例代码
    目录导入需要的包设置变量写数字绘制时针完整代码导入需要的包设置变量 from datetime import datetime from pygame.locals import *...
    99+
    2024-04-02
  • R语言绘制饼状图代码实例
    R编程语言有许多库来创建图表和图表。 饼图是将值表示为具有不同颜色的圆的切片。 切片被标记,并且对应于每个片的数字也在图表中表示。 在R语言中,饼图是使用pie()函数创建的,它使用...
    99+
    2024-04-02
  • Python matplotlib.pyplot.hist()绘制直方图的方法实例
    目录一、matplotlib.pyplot.hist()语法二、绘制直方图①绘制简单直方图②:各个参数绘制的直方图(1)histtype参数(设置样式bar、barstacked、s...
    99+
    2024-04-02
  • HTML5 Canvas中有哪些绘制椭圆的方法
    本篇内容介绍了“HTML5 Canvas中有哪些绘制椭圆的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2024-04-02
  • HTML5 Canvas中绘制椭圆的方法有哪些
    本篇内容介绍了“HTML5 Canvas中绘制椭圆的方法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作