SwiftUI直通车系列(5)—— 自定义绘制

Easter79
• 阅读 558

SwiftUI直通车系列(5)—— 自定义绘制

前情回顾:

SwiftUI直通车系列(1)—— 视图的布局与组织

SwiftUI直通车系列(2)—— 列表视图

SwiftUI直通车系列三(3)—— 使用导航

SwiftUI直通车系列(4)—— 处理用户交互

    在UI开发中,我们经常会使用到各式各样的图标或图形。通常,我们可以直接使用图片来渲染图形,在SwiftUI中也提供了相关的接口来对图形绘制提供支持,理论上,我们可以不使用外部图片来自定义绘制出我们想要渲染的图形。

一、图形绘制

    首先,在定义SwiftUI组件时,我们可以通过路径的定义绘制其要表现的UI图形,例如要在页面上显示一个菱形图形,示例代码如下:

struct DrawTestView:View {
    var body: some View {
        Path { path in
            let width = 200
            let height = 200
            path.move(to: CGPoint(x: width, y: height))
            path.addLine(to: CGPoint(x: 100, y: 400))
            path.addLine(to: CGPoint(x: 200, y: 600))
            path.addLine(to: CGPoint(x: 300, y: 400))
        }.fill(Color.red)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        DrawTestView()
    }
}

效果如下图所示:

SwiftUI直通车系列(5)—— 自定义绘制

上面的代码很好理解,使用Path在定义View时,move方法用来进行绘制点的移动,简单理解,如果我们将图形的绘制类比与用笔作画,则move方法的作用就是移动笔尖的位置。addLine方法用来向视图上画一条线,定义完了路径后,调用fill方法用来进行图形内部颜色的填充。如上代码所示,实际上我们只画了三条线,系统默认将三条线及最后一个点与原点的连线组成的图形内部进行了颜色的填充,如果我们不对内部进行颜色填充,只将线的颜色显示出来,就更加直观了,代码如下:

struct DrawTestView:View {
    var body: some View {
        Path { path in
            let width = 200
            let height = 200
            path.move(to: CGPoint(x: width, y: height))
            path.addLine(to: CGPoint(x: 100, y: 400))
            path.addLine(to: CGPoint(x: 200, y: 600))
            path.addLine(to: CGPoint(x: 300, y: 400))
        }.stroke(Color.red,lineWidth: 10)
    }
}

效果如下图所示:

SwiftUI直通车系列(5)—— 自定义绘制

与addLine的使用方法类似,我们还可以通过添加矩形、椭圆、贝塞尔曲线等等方法来绘制图形,示例代码如下:

struct DrawTestView:View {
    var body: some View {
        Path { path in
            let width = 200
            let height = 200
            path.move(to: CGPoint(x: width, y: height))
            path.addLine(to: CGPoint(x: 100, y: 400))
            path.addLine(to: CGPoint(x: 200, y: 600))
            path.addLine(to: CGPoint(x: 300, y: 400))
            path.addRect(CGRect(x: 20, y: 20, width: 30, height: 30))
            path.addEllipse(in: CGRect(x: 60, y: 20, width: 60, height: 30))
            path.addCurve(to: CGPoint(x: 100, y: 100), control1: CGPoint(x: 160, y: 100), control2: CGPoint(x: 60, y: 80))
            path.addRoundedRect(in: CGRect(x: 140, y: 20, width: 50, height: 40), cornerSize: CGSize(width: 20, height: 20))
        }.stroke(Color.red,lineWidth: 3)
    }
}

效果如下图所示:

SwiftUI直通车系列(5)—— 自定义绘制

二、设置绘制属性

    在SwiftUI中,完成了图形的定义是一步,之后我们还需要将图形描边绘制或填充绘制。无论是描边绘制还是填充绘制,我们都可以定制化的对绘制属性进行控制,例如下面的示例代码:

struct DrawTestView:View {
    var body: some View {
        VStack {
            Path { path in
                let width = 200
                let height = 0
                path.move(to: CGPoint(x: width, y: height))
                path.addLine(to: CGPoint(x: 100, y: 200))
                path.addLine(to: CGPoint(x: 200, y: 400))
                path.addLine(to: CGPoint(x: 300, y: 200))
                path.addLine(to: CGPoint(x: 200, y: 0))
            }.stroke(style: StrokeStyle(lineWidth: 3, lineCap: CGLineCap.butt, lineJoin: .bevel, miterLimit: 2, dash: [15,4], dashPhase: 2)).foregroundColor(.blue)
            Path { path in
                let width = 200
                let height = 20
                path.move(to: CGPoint(x: width, y: height))
                path.addLine(to: CGPoint(x: 100, y: 220))
                path.addLine(to: CGPoint(x: 200, y: 420))
                path.addLine(to: CGPoint(x: 300, y: 220))
            }.fill(LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .top, endPoint: .bottom))
        }
    }
}

效果如下图所示:

SwiftUI直通车系列(5)—— 自定义绘制

对于描边绘制,我们可以设置线的风格,间距,转角风格等。对于填充绘制,我们可以为其设置渐变填充,上面代码示例的是线性渐变效果,系统还提供了圆心渐变等功能。

三、简单的图形变换和组合

    有规律的对绘制的图形进行变换和组合往往可以得到非常美观的复合图形,例如对于上面绘制的菱形,我们可以通过修改透明度进行图形组合,并使用旋转变换的方式使其构建出更加美观的图标,修改代码如下:

struct DrawTestView:View {
    let angle:Angle
    var body: some View {
            Path { path in
                let width = 250
                let height = 150
                path.move(to: CGPoint(x: width, y: height))
                path.addLine(to: CGPoint(x: 100, y: 300))
                path.addLine(to: CGPoint(x: 200, y: 450))
                path.addLine(to: CGPoint(x: 300, y: 100))
            }.fill(LinearGradient(gradient: Gradient(colors: [Color.red, Color.blue]), startPoint: .top, endPoint: .bottom)).rotationEffect(angle, anchor: .center)
        }
}

struct DrawContent:View {
    var body: some View {
        ZStack{
            ForEach(0 ..< 10) { i in
                DrawTestView(angle: Angle(degrees:Double(36*i))).opacity(0.3)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        DrawContent()
    }
}

效果如下图所示:

SwiftUI直通车系列(5)—— 自定义绘制

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Easter79 Easter79
2年前
SwiftUI直通车系列(3)—— 使用导航
SwiftUI直通车系列三(3)——使用导航  关于SwiftUI,我们前两篇博客介绍了独立组件的布局与属性设置相关内容,并且介绍了开发中最常用的列表视图的使用。但是一个完整的应用程序不可能是单界面的,如何使用SwiftUI进行界面间的导航跳转,是我们本博客讨论的重点。前两篇博客地址如下:Swi
Easter79 Easter79
2年前
SwiftUI直通车系列(4)—— 处理用户交互
SwiftUI直通车系列(4)——处理用户交互前情回顾:SwiftUI直通车系列(1)——视图的布局与组织(https://my.oschina.net/u/2340880/blog/4529951)SwiftUI直通车系列(2)——列表视图(https://my.oschina.n
Easter79 Easter79
2年前
SwiftUI直通车系列(1)—— 视图的布局与组织
SwiftUI直通车系列(1)——视图的布局与组织一、引言    SwiftUI提供了一种更快、更高效也更简单的页面开发方式。我们知道相对于ObjectiveC,Swift语言本身就更加高效简洁,SwiftUI采用了结构化的布局方式,使得应用的界面开发更加直观快速。本系列博客,
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Easter79 Easter79
2年前
SwiftUI直通车系列(6)—— 使用动画
SwiftUI直通车系列(6)——使用动画   本系列博客是针对SwiftUI开发框架的快速入门介绍,之前系列博客地址:SwiftUI直通车系列(1)——视图的布局与组织(https://my.oschina.net/u/2340880/blog/4529951)SwiftUI直通车系列
Wesley13 Wesley13
2年前
Java日期时间API系列35
  通过Java日期时间API系列1Jdk7及以前的日期时间类(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2Fxkzhangsanx%2Fp%2F12032719.html)中得知,Java8以前除了java.sql.Timestamp扩充
Easter79 Easter79
2年前
SwiftUI直通车系列(2)—— 列表视图
SwiftUI直通车系列(2)——列表视图  列表视图的开发中非常常用的页面元素。SwiftUI中也有专门用来渲染列表的元素提供。一、编写行视图   列表实际上是一组行视图的组合,在布局列表视图之前,你首先需要定义好行视图的布局。例如,我们使用一个Image元素和两个Tex
Easter79 Easter79
2年前
SwiftUI 跨组件数据传递
作者:Cyandev,iOS和MacOS开发者,目前就职于字节跳动0x00前言众所周知,SwiftUI的开发模式与React、Flutter非常相似,即都是声明式UI,由数据驱动(产生)视图,视图也会与数据自动保持同步,框架层会帮你处理“绑定”的问题。在声明式UI中不存在命令式地让一个视图变成xxx
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k