• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • SwiftUI學習筆記[path繪制]

    標簽: IOS專欄  SwiftUI  SwiftUI繪制  IOS繪制  IOS自定義  Swift繪制

    前言

    繪制的底層是強大的,我們所用的各端語言只是在現代UI追求的步伐中和用戶喜好的交互中求同存異,抽取封裝出自成個性風格的UI控件,當然面對萬億級別的客戶各個平臺的UI庫出也不可能滿足所有的客戶需求,當然一門語言的可制定性也意味著其強大,幾乎每個平臺都提供了接口讓開發者創造其UI的可能性,更可能的能滿足客戶需求。

    一,Path 繪制【直線、圓弧、圓錐曲線、貝塞爾曲線等】

    1.Path

    • SwiftUI兩種方式來自定義繪圖:路徑(path)和形狀(shaper)。路徑是一系列繪圖指令,例如:從這里開始moveTo到哪里lineTo,在哪里添加形狀例如增加矩形,圓圈,橢圓,曲線其他的線段等addRect,addCircle,addPath...”,所有這些都使用絕對坐標。形狀是用路徑構建的,所以一旦你理解了路徑,形狀就很容易了。而且,就像路徑、顏色和漸變一樣,形狀也是視圖,這意味著我們可以將它們與文本視圖、圖像等一起配合使用。

      方法作用案例
      path繪制的基本單位path.很多方法【move,addLine,addLines,addArc…】
      move即從哪一點開始path.move(to: CGPoint(x:0, y:0))
      addLine連接到某一點path.addLine(to: CGPoint(x:100, y:100))

    2.Path畫線

    繪制會在視圖中進行,寫過Android和Flutter以及H5的都知道,默認的繪制坐標系原點默認都在畫布canvas的左上角,如果畫布占滿屏幕也就是屏幕的左上角。我們繪制一個從(0,0)開始到(100,100)的線段,我們來測驗是否同其他端一樣:

    struct SwiftUI_Path01: View {
        var screenBounds:CGRect = UIScreen.main.bounds//mainScreen().bounds
        var body: some View {
            //由于Path也是視圖我們可以直接在View里面進行繪制如下。
            Path{path in
                path.move(to: CGPoint(x:0, y:0))
                path.addLine(to: CGPoint(x:100, y:100))
            }.stroke(Color.red, lineWidth:3)//stroke設置path顏色?
            .border(Color.blue,width:2)//border給畫布繪制邊框
        }
    }
    
    
    struct SwiftUI_Path01_Previews: PreviewProvider {
        static var previews: some View {
            SwiftUI_Path01()
        }
    }
    

    3.Path畫網格

    坐標系如下:左上角原點,右下方方向也就意味著屏幕左上角坐標為(0,0),屏幕左下角坐標為(0,screenHeight),屏幕右上角為(0,scrrenWidth),屏幕右下角為(screenWidth,scrrenHeight),相當于數學坐標系的第一象限

    接下來我們來繪制一個網格,這樣我們可以明確的看到我們的線所經過的點,后面的學習也會很好的定位了。什么是網格呢如下:

    • 我們先來一個左上角為圓心的坐標系。首先我們明確圓心在左上角。按照間距20來畫,然后我們橫著畫線的根數=height(高度)/20,豎著畫的根數=width(寬度)/20,如下圖,循環繪制橫線和豎線即可生成方格坐標系。這里需要知道獲取當前控件內部寬高的容器控件GeometryReader如果這里使用屏幕寬和高度就需要用UIScreen.main.bounds

    首先我們來繪制橫線代碼如下,我們畫一把刀最好有坐標系可以根據坐標點進行精確的定位。

    import SwiftUI
    
    struct SwiftUIView_Path02: View {
        var screenBounds:CGRect = UIScreen.main.bounds//mainScreen().bounds
        var body: some View {
            //看了Api也知道Path也是視圖我們可以直接在View里面進行繪制如下。
            let mwidth=screenBounds.width;
            let mheight=screenBounds.height;
            let vcount=mheight/20
            Path{path in
                for i in 0..<Int(vcount){
                    path.move(to: CGPoint(x:0,y:i*20))
                    path.addLine(to:CGPoint(x:Double(mwidth),y:(20.0*Double(i))))
                 
                }
            }.stroke(Color.gray, lineWidth:1)//stroke設置path顏色?
            .border(Color.blue,width:2)//border給畫布繪制邊框
        }
    }
    
    struct SwiftUIView_Path02_Previews: PreviewProvider {
        static var previews: some View {
            SwiftUIView_Path02()
        }
    }
    
    

    效果如下

    • 同樣方法的畫豎著的線代碼如下。
    struct SwiftUIView_Path02: View {
        var screenBounds:CGRect = UIScreen.main.bounds//mainScreen().bounds
        var body: some View {
            //看了Api也知道Path也是視圖我們可以直接在View里面進行繪制如下。
            let mwidth=screenBounds.width;
            let mheight=screenBounds.height;
            let vcount=mheight/20
            let hcount=mwidth/20
            Path{path in
                //畫橫著的線
                for i in 0..<Int(vcount){
                    path.move(to: CGPoint(x:0,y:i*20))
                    path.addLine(to:CGPoint(x:Double(mwidth),y:(20.0*Double(i))))
                 
                }
                
                //畫豎著的線
                for i in 0..<Int(hcount+1){
                    path.move(to: CGPoint(x:i*20,y:0))
                    
                    path.addLine(to:CGPoint(x:20*i,y:Int(mheight)))
                 
                }
                
                
            }.stroke(Color.gray.opacity(0.5), lineWidth:1)//stroke設置path顏色?
            .border(Color.blue,width:2)//border給畫布繪制邊框
        }
    }
    
    • 展示如下

    4.Path畫刀

    1.繪制刀: lineTo

    接下來我們在所畫的坐標系中進行繪制一把用矩形繪制的刀。至于我們的弧度要求等我們學習完塞貝爾曲線后面再來。下面零時畫來個刀…其實我的畫畫水平不錯的??。

    • 代碼開始 首先我們找一點,刀把的左上角開始(x:180,y:50),依次根據感覺畫出坐標點即可代碼如下:
    import SwiftUI
    
    struct SwiftUIView_Path02: View {
        var screenBounds:CGRect = UIScreen.main.bounds//mainScreen().bounds
        var body: some View {
            //看了Api也知道Path也是視圖我們可以直接在View里面進行繪制如下。
            let mwidth=screenBounds.width;
            let mheight=screenBounds.height;
            let vcount=mheight/20
            let hcount=mwidth/20
            ZStack{
            Path{path in
                //畫橫著的線
                for i in 0..<Int(vcount){
                    path.move(to: CGPoint(x:0,y:i*20))
                    path.addLine(to:CGPoint(x:Double(mwidth),y:(20.0*Double(i))))
                 
                }
                
                //畫豎著的線
                for i in 0..<Int(hcount+1){
                    path.move(to: CGPoint(x:i*20,y:0))
                    path.addLine(to:CGPoint(x:20*i,y:Int(mheight)))
                 
                }
                //刀的開始
                path.move(to:CGPoint(x:180,y:40))
                path.addLine(to: CGPoint(x: 240, y:20))
                path.addLine(to: CGPoint(x:260,y:40))
                path.addLine(to: CGPoint(x:225,y:40))
                path.addLine(to: CGPoint(x:225,y:140))
                path.addLine(to: CGPoint(x:280,y:180))
                path.addLine(to: CGPoint(x:270,y:200))
                path.addLine(to: CGPoint(x:225,y:190))
                path.addLine(to: CGPoint(x:255,y:700))
                path.addLine(to: CGPoint(x:180,y:600))
                path.addLine(to: CGPoint(x:190,y:180))
                path.addLine(to: CGPoint(x:170,y:170))
                path.addLine(to: CGPoint(x:180,y:140))
                path.addLine(to: CGPoint(x:198,y:130))
                path.addLine(to: CGPoint(x:199,y:40))
                path.addLine(to: CGPoint(x:180,y:40))
                
            }.stroke(Color.gray.opacity(0.5), lineWidth:1)//stroke設置path顏色?
            .border(Color.blue,width:2)//border給畫布繪制邊框
    
            }
        }
    }
    
    struct SwiftUIView_Path02_Previews: PreviewProvider {
        static var previews: some View {
            SwiftUIView_Path02()
        }
    }
    

    效果如下:

    2.改變Path的顏色 .stroke()

    我們發現這個上一個圖中刀的路徑和坐標網格都是灰色,能不能搞個其他的顏色或者貼個材質,ok完全沒問題,我們慢慢來。

    • 這里我算是比較頭大的,至少相對比Flutter和Android,Swift在繪制中將Path提升為視圖級別而且沒有paint,反而開發者做了大量的無用且多余的工作。我們在Flutter中通過在一個畫布canvas上可以用任意多個path我們只需要修改畫筆的顏色既可以修改任意線段的顏色,代碼集中其好理解。而Swift中我們無法修改在一個Path繪制的多條鏈接線段有不同的顏色。例如:我在上面同一個Path里同時面繪制了底圖坐標系,我只是想修改一下刀的顏色和底圖坐標系設置不一樣,但是并沒有提供畫筆,一條path有且只有一個顏色,這點我認為沒錯。但是我們是間斷的繪制線段卻無法修改想要修改線段的顏色或者粗細等…這里讓我在繪制中產生了抵觸。

    但是我們能不能實現底圖灰色,刀紅色的效果了,毫無疑問是可以的。只要你喜歡探索和想象可能度娘上沒有的你也可以創造,這里我是想到Path既然是視圖那么我們可以用ZStack來當作畫布,那么ZStack里面可以扔無數的Path路徑視圖了。所以我們將底圖坐標系部分和刀部分分開扔到ZStack里面代碼如下:

    import SwiftUI
    
    struct SwiftUIView_Path02: View {
        var screenBounds:CGRect = UIScreen.main.bounds//mainScreen().bounds
        var body: some View {
            //看了Api也知道Path也是視圖我們可以直接在View里面進行繪制如下。
            let mwidth=screenBounds.width;
            let mheight=screenBounds.height;
            let vcount=mheight/20
            let hcount=mwidth/20
            ZStack{
                //一坐標系部分
                Path{path in
                    //畫橫著的線
                    for i in 0..<Int(vcount){
                        path.move(to: CGPoint(x:0,y:i*20))
                        path.addLine(to:CGPoint(x:Double(mwidth),y:(20.0*Double(i))))
                     
                    }
                    
                    //畫豎著的線
                    for i in 0..<Int(hcount+1){
                        path.move(to: CGPoint(x:i*20,y:0))
                        path.addLine(to:CGPoint(x:20*i,y:Int(mheight)))
                     
                    }
                   
                }.stroke(Color.gray.opacity(0.5), lineWidth:1)//stroke設置path顏色?
                .border(Color.blue,width:2)//border給畫布繪制邊框
                //2.刀部分的path
                Path{path in
                    path.move(to:CGPoint(x:180,y:40))
                    path.addLine(to: CGPoint(x: 240, y:20))
                    path.addLine(to: CGPoint(x:260,y:40))
                    path.addLine(to: CGPoint(x:225,y:40))
                    path.addLine(to: CGPoint(x:225,y:140))
                    path.addLine(to: CGPoint(x:280,y:180))
                    path.addLine(to: CGPoint(x:270,y:200))
                    path.addLine(to: CGPoint(x:225,y:190))
                    path.addLine(to: CGPoint(x:255,y:700))
                    path.addLine(to: CGPoint(x:180,y:600))
                    path.addLine(to: CGPoint(x:190,y:180))
                    path.addLine(to: CGPoint(x:170,y:170))
                    path.addLine(to: CGPoint(x:180,y:140))
                    path.addLine(to: CGPoint(x:198,y:130))
                    path.addLine(to: CGPoint(x:199,y:40))
                    path.addLine(to: CGPoint(x:180,y:40))
                    
                }.stroke(Color.red.opacity(0.5), lineWidth:11)//stroke設置path顏色?
                .border(Color.blue,width:2)//border給畫布繪制邊框
               
            }
        }
    }
    
    struct SwiftUIView_Path02_Previews: PreviewProvider {
        static var previews: some View {
            SwiftUIView_Path02()
        }
    }
    

    3.Path閉合區域填沖顏色或者漸變色:.fill(..)

    可能有人需要給這個區域填充顏色那么我們只需要.fill進行填充代碼如下:

    • 記住fill和stroke不能共存
        //給路徑包裹區域填充漸變或者顏色
        Path{path in
    
        }.fill(LinearGradient(gradient: Gradient(colors: [.white,.pink,.clear,.gray,.green,.purple,.black,.blue,.red,.orange]), startPoint:.top, endPoint:.bottom))
    
    

    4.給Path路徑或者Path閉合區域添加陰影:.shandow(..)

     //給Path路徑添加顏色
     Path{path in
                    path.move(to:CGPoint(x:180,y:40))
                    path.addLine(to: CGPoint(x: 240, y:20))
                    path.addLine(to: CGPoint(x:260,y:40))
                    path.addLine(to: CGPoint(x:225,y:40))
                    path.addLine(to: CGPoint(x:225,y:140))
                    path.addLine(to: CGPoint(x:280,y:180))
                    path.addLine(to: CGPoint(x:270,y:200))
                    path.addLine(to: CGPoint(x:225,y:190))
                    path.addLine(to: CGPoint(x:255,y:700))
                    path.addLine(to: CGPoint(x:180,y:600))
                    path.addLine(to: CGPoint(x:190,y:180))
                    path.addLine(to: CGPoint(x:170,y:170))
                    path.addLine(to: CGPoint(x:180,y:140))
                    path.addLine(to: CGPoint(x:198,y:130))
                    path.addLine(to: CGPoint(x:199,y:40))
                    path.addLine(to: CGPoint(x:180,y:40))
                }.stroke(LinearGradient(gradient: Gradient(colors: [.white,.pink,.clear,.gray,.green,.purple,.black,.blue,.red,.orange]), startPoint:.top, endPoint:.bottom),lineWidth:3)
                .shadow(color: Color.pink,radius: 12.0,x: CGFloat(11),y: CGFloat(11))
                
    //給Path閉合區域添加漸變色
      Path{path in
                    path.move(to:CGPoint(x:180,y:40))
                    path.addLine(to: CGPoint(x: 240, y:20))
                    path.addLine(to: CGPoint(x:260,y:40))
                    path.addLine(to: CGPoint(x:225,y:40))
                    path.addLine(to: CGPoint(x:225,y:140))
                    path.addLine(to: CGPoint(x:280,y:180))
                    path.addLine(to: CGPoint(x:270,y:200))
                    path.addLine(to: CGPoint(x:225,y:190))
                    path.addLine(to: CGPoint(x:255,y:700))
                    path.addLine(to: CGPoint(x:180,y:600))
                    path.addLine(to: CGPoint(x:190,y:180))
                    path.addLine(to: CGPoint(x:170,y:170))
                    path.addLine(to: CGPoint(x:180,y:140))
                    path.addLine(to: CGPoint(x:198,y:130))
                    path.addLine(to: CGPoint(x:199,y:40))
                    path.addLine(to: CGPoint(x:180,y:40))
    
                }.fill(LinearGradient(gradient: Gradient(colors: [.white,.pink,.clear,.gray,.green,.purple,.black,.blue,.red,.orange]), startPoint:.top, endPoint:.bottom))//.stroke(Color.red.opacity(0.5)
                .shadow(color: Color.pink,radius: 12.0,x: CGFloat(11),y: CGFloat(11))
    
    

    • 小總結:Path作為視圖我們可以通過stroke(_ content: S, lineWidth: CGFloat = 1)來設置路徑的顏色和粗細,.fill(color)來設置填充色等。填補了無Flutter以及Android里的Paint的缺陷。到此我們可以總結相關的屬性如下表:

      方法作用案例
      .fill通過顏色或者漸變來填充路徑閉合區域.fill(Color.red)fill(LinearGradient(gradient: Gradient(colors: [.white,.pink,.clear,.gray,.green,.purple,.black,.blue,.red,.orange]), startPoint:.top, endPoint:.bottom))
      .stroke通過顏色或漸變來填充路徑顏色.stroke(Color.red,lineWidth:3)stroke(LinearGradient(gradient: Gradient(colors: [.white,.pink,.clear,.gray,.green,.purple,.black,.blue,.red,.orange])


    慢慢寫…晚上回家看老婆讓不讓寫了…明天繼續

    版權聲明:本文為m0_37667770原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/m0_37667770/article/details/110183543

    智能推薦

    學習筆記---繪制文字

    Paint和TextPaint,不能直接讓文字換行。需要其他額外操作。 代碼: FontView 布局代碼中使用:...

    CMD學習筆記——tree、path和time

    tree以圖形格式顯示目錄結構 如果需要以圖形格式顯示路徑或驅動器中的磁盤的目錄結構,可以使用tree命令 語法 參數 參數 說明 drive: 指定包含顯示目錄結構的磁盤驅動器 path 指定要顯示目錄結構的目錄 /f 顯示每個目錄中的文件名 /a 指定tree使用文本字符而不是圖形字符顯示鏈接子目錄的行 例1:以圖形格式顯示目錄結構 例2:顯示每個目錄中的文件名 例3:指定tree使用文本字符...

    Nodejs學習筆記——路徑模塊path

    __filename與__dirname 引入模塊 使用...

    opencv學習筆記 ----繪制直方圖

    什么是直方圖? 圖像的直方圖是每個點像素值的個數在一個圖中展現,每個通道的像素有多少。 直方圖是圖像一個重要的性質(分析圖片的手段)。 計算直方圖 ???????opencv中直接計算直方圖的函數,在matplotlib  如圖,使用函數后。橫坐標是像素的值,縱坐標是個數。 若想要分開顏色 函數的參數cv.calcHist(images,channels,mask,histSize,ra...

    Qt學習筆記 繪制文本

    先從最簡單任務開始:在 widget 的左上角(0, 0)處繪制字符串 jEh。 …… 出師不利,本以為是很簡單的一件事,那還不手到擒來么,不曾想結果卻讓人大跌眼鏡,只顯示出了 j 的小尾巴。如果把 y 的值設置大一些,如 150,則就可以完全顯示出來了。但是,y 要多大才合適?不能一點一點的試吧,否則字體變了,y 的值又不合適了,完全不科學,這要如何是好? FontM...

    猜你喜歡

    Matlab學習筆記——圖形繪制

    寫在這里的初衷,一是備忘,二是希望得到高人指點,三是希望能遇到志同道合的朋友。 目錄 圖形繪制 1.正弦曲線繪制 2.常用三角函數曲線的繪制 圖形繪制 1.正弦曲線繪制 以產生一個簡單的正弦函數曲線為例來說明圖形的繪制。 從這一過程可以看出,在MATLAB中建立曲線圖形是很方便的。 得到的正弦曲線如圖所示: 2.常用三角函數曲線的繪制 將圖形窗口進行分割,從而繪制出多條曲線。 例如,將圖形窗口分割...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    精品国产乱码久久久久久蜜桃不卡