在Swift UI中使用相对坐标简化Shape绘制

这篇具有很好参考价值的文章主要介绍了在Swift UI中使用相对坐标简化Shape绘制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在SwiftUI中使用相对坐标Shape绘制

Swift UI 提供了一些内置的基本形状,如矩形,圆角矩形,圆和椭圆等。 实际开发过程中,这些形状远远不够,需要增加新的定制形状,比如,三角形,或者复杂一点的水滴形状等。

要增加新的自定义形状,只要实现SwiftUI 提供Shape协议即可。下面是自定义一个三角形的例子:

struct Triangle: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let centerX = rect.width / 2
        let centerY = rect.height / 2
        path.move(to: CGPoint(x: centerX, y: 0))
        path.addLine(to: CGPoint(x: 0, y: centerY))
        path.addLine(to: CGPoint(x: centerX, y: rect.height))
        path.closeSubpath()
        return path
    }
}

在View中可以直接使用上述三角形:

#Preview
{
    HStack
    {
        Triangle()
            .stroke(Color.red)
            .frame(width: 100, height: 100)
            .background(Color.gray.opacity(0.  3))
  }   
}

显示效果如下:

在Swift UI中使用相对坐标简化Shape绘制,SWIFT 学习笔记,swift,ui,开发语言

在Shape协议中,所有的形状都在一个容器矩形(CGRect)中绘制。
绘制的关键是在如何确定形状中的一些关键点,并最终用容器矩形的四个参数minX,minY,maxX,maxY表达出这些关键点。 (矩形本身的长和宽也可以用上面四个参数表达)

上面绘制三角形的代码其实很简单,这主要是因为三角形很简单。但仔细观察 ,可以发现绘制代码并不好理解, 代码中充斥着各种CGPoint,这些CGPoint有些是关键点,有些是辅助点,它们的坐标需要根据 rect计算得出,都需要我们转几个弯才能理解。

想象一下,如果定制形状比较复杂,特别是一些有控制点的曲线形状,上述计算CGPoint的过程就非常容易出错,而且由于都是变量,对这些CGPoint在rect中的位置也没有直观认识。如果这些形状还需要一些外部参数控制的话,情况可能会变得更糟糕。

使用相对坐标简化绘制

使用相对坐标可以解决上述问题。我们首先引进相对坐标的概念,定义屏幕上任意点(X,Y)相对容器矩形rect的相对坐标为(ratioX,ratioY),其中,ratiXratioY 定义如下:

ratioX  =X - minX )/(maxX-minX)
ratioY  =Y - minY )/(maxY-minY)

相对坐标这个名称其实不尽合理,从数学上看,归一坐标或者标准坐标或正则坐标也许更合理些,不过这些名词不那么接地气。

相对坐标的主要思路是,将容器矩形rect,无论大小,都缩放到一个单位矩形,这在数学上可以对rect的坐标系进行了两次变换,一次平移变换,一次伸缩变换来实现。

容易看出,如果点(X,Y)位于矩形rect内,则其相对坐标分量均大于等于0且小于等于1 。实际上,点(X,Y)可以是屏幕上任何位置,可以在矩形内也可以在矩形外,因此其相对坐标不必都在0和1之间,大于1,小于0均是有可能的。实际上,由于形状的绘制均在容器矩形内,所以,其相对坐标的范围也就都在0和1之间了。

比较一下分别用相对坐标和绝对坐标表达的容器矩形中的几个关键点

位置 绝对坐标 相对坐标
矩形左下角 (minX,minY) (0,0)
矩形右上角 (maxX,maxY) (1,1)
矩形中心 (midX,midY) (0.5,0.5)

可以看到,相对于绝对坐标,相对坐标的表达更加简单,清晰直观。这正是我们简化Shape形状绘制的基础。

使用相对坐标进行绘制

如果已经知道相对坐标(ratioX,ratioY),则我们很容易用下面公式计算其绝对坐标:

X   =   minX + ratioX*(maxX-minX)
Y   =   minY + ratioY*(maxY-minY)

为了使用相对坐标进行绘制,我们必须按上述公式将相对坐标转换成绝对坐标,为此,首先对rect进行扩展,使之具有处理相对坐标的能力:

extension CGRect
{
    func xy(_ ratioX:CGFloat,_ ratioY:CGFloat )->CGPoint
    {
        return CGPoint (x: self.minX + ratioX * self.width ,y:self.minY + ratioY  * self.height )
    }
     
}     
  //备注容器矩形的长和宽
  //width   =  maxX - minX  
  //height  =  maxY - minY  

上述扩展为CGRect类增加一个xy()的方法,该函数接受相对坐标为参数,用我们的上述公式将该相对坐标转换为绝对坐标,用CGPoint对象表示,各种具体的绘制方法均以CGPoint
对象为基础进行。有了上述扩展后,我们就可以用相对坐标绘制了。

下面是使用相对坐标后的三角形绘制代码,

struct TriangleA: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: rect.xy(0.5, 0))
        path.addLine(to: rect.xy(0, 0.5))
        path.addLine(to: rect.xy(0.5, 1)) 
        path.closeSubpath()
        return path
    }
}

可以看到,新代码不仅更简洁,更清晰,也更容易理解了。

同时使用两种方式绘制三角形:

#Preview
{
    HStack
    {
        //按绝对坐标绘制的三角形
        Triangle()
            .stroke(Color.red)
            .frame(width: 100, height: 100)
            .background(Color.gray.opacity(0.3))
        //按相对坐标绘制的三角形
         TriangleA()
            .stroke(Color.blue)
            .frame(width: 100, height: 100)
            .background(Color.gray.opacity(0.3))
   }   
    
}

下面是显示效果,红色色使用绝对坐标绘制的三角形,蓝色是使用相对坐标绘制的三角形。可以看到,二者绘制效果完全一致:
在Swift UI中使用相对坐标简化Shape绘制,SWIFT 学习笔记,swift,ui,开发语言文章来源地址https://www.toymoban.com/news/detail-840577.html

到了这里,关于在Swift UI中使用相对坐标简化Shape绘制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Swift UI 3

    存储文本字段值需要使用字符串进行存储 Textfieled建立文本框 文本框没有限制数字 美元符号绑定自动文本 使用文本框进行文字输入处理 确定键盘类型   新建一个键盘 text使用美元符号进行双向绑定 navigation进行添加导航视图 使用for each进行强制循环                    

    2024年04月27日
    浏览(21)
  • Swift UI

    创建新的swift ui应用程序时,会获得一系列文件和100行代码。大部分代码什么都不做但是作为占位符(Xcode在左边看到文件) 项目导航器应用程序委托或swift包含用于管理您的代码的代码应用程序 过去通常在那里添加代码但是如今很少见 但swift包含用于您的应用程序中启动窗

    2024年03月26日
    浏览(34)
  • swift ui 布局 ——Stack(HStack、VStack、ZStack)

    将其子视图排列在水平线上 默认子视图是水平中心对齐的,可添加alignment  修改位置,alignmet 的值有 bottom   top  center等,可自己查看api 将其子视图排列在垂直线上 默认子视图是垂直中心中心对齐的,可添加alignment  修改位置,alignmet 的值有 leading   trailing  center等 用于覆盖

    2024年02月05日
    浏览(26)
  • iOS从UI内存地址到读取成员变量(oc/swift)

    开发调试时,我们发现bug时常首先是从UI显示发现异常,下一步才会去定位UI相关连的数据的。XCode有给我们提供一系列debug工具,但是很多人可能还没有形成一套稳定的调试流程,因此本文尝试解决这个问题,顺便提出一个 暴论 :UI显示异常问题只需要两个步骤就能完成定位

    2023年04月19日
    浏览(56)
  • iOS开发Swift-3-UI与按钮Button-摇骰子App

    1.创建新项目Dice  2.图标  删去AppIcon,将解压后的AppIcon.appiconset文件拖入Assets包。  3.将素材点数1-6通过网页制作成2x,3x版本并拖入Asset。  4.设置对应的UI。  5.拖入Button组件并设置style。  6.Ctrl加拖拽将Button拖拽到ViewController里,并设置Connection,Name等,并点击Connect。  同样

    2024年02月11日
    浏览(28)
  • Swift Combine 通过用户输入更新声明式 UI 从入门到精通十五

    Combine 系列 Swift Combine 从入门到精通一 Swift Combine 发布者订阅者操作者 从入门到精通二 Swift Combine 管道 从入门到精通三 Swift Combine 发布者publisher的生命周期 从入门到精通四 Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五 Swift Combine 订阅者Subscriber的生命周

    2024年02月20日
    浏览(25)
  • Swift Combine 合并多个管道以更新 UI 元素 从入门到精通十七

    Combine 系列 Swift Combine 从入门到精通一 Swift Combine 发布者订阅者操作者 从入门到精通二 Swift Combine 管道 从入门到精通三 Swift Combine 发布者publisher的生命周期 从入门到精通四 Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五 Swift Combine 订阅者Subscriber的生命周

    2024年03月13日
    浏览(31)
  • Swift Combine 级联多个 UI 更新,包括网络请求 从入门到精通十六

    Combine 系列 Swift Combine 从入门到精通一 Swift Combine 发布者订阅者操作者 从入门到精通二 Swift Combine 管道 从入门到精通三 Swift Combine 发布者publisher的生命周期 从入门到精通四 Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五 Swift Combine 订阅者Subscriber的生命周

    2024年02月19日
    浏览(24)
  • Swift学习内容精选(二)

    Swift 类是构建代码所用的一种通用且灵活的构造体。 我们可以为类定义属性(常量、变量)和方法。 与其他编程语言所不同的是,Swift 并不要求你为自定义类去创建独立的接口和实现文件。你所要做的是在一个单一文件中定义一个类,系统会自动生成面向其它代码的外部接

    2024年02月09日
    浏览(33)
  • IOS-闭包学习-Swift

    闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数(Lambdas)比较相似。 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。被称为包裹常量和变量。 Swift 会为你管理在捕

    2024年01月24日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包