最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

SwiftUI學(xué)習(xí)100天(Day43 - 項(xiàng)目 9,第一部分)

2023-02-15 12:00 作者:愛(ài)上樹(shù)の蝸牛  | 我要投稿

原創(chuàng)鏈接:https://www.hackingwithswift.com/100/swiftui

以下內(nèi)容僅供學(xué)習(xí)參考:

今天開(kāi)始另一個(gè)新技術(shù)項(xiàng)目,我們將專(zhuān)注于繪圖。這是 SwiftUI 的一個(gè)領(lǐng)域,你可能認(rèn)為你不需要太多,但事實(shí)并非如此:SwiftUI 使高性能繪圖變得如此簡(jiǎn)單,每個(gè)人都可以訪(fǎng)問(wèn),你會(huì)找到可以發(fā)揮你的技能的地方在你構(gòu)建的幾乎每個(gè)應(yīng)用程序中。

繪畫(huà)的另一個(gè)好處——這將在本項(xiàng)目的第二部分和第三部分中變得更加明顯——有助于營(yíng)造一種嬉戲感。在接下來(lái)的幾天里,你會(huì)發(fā)現(xiàn)只需幾行代碼就可以創(chuàng)建漂亮的設(shè)計(jì),而我在準(zhǔn)備我的示例時(shí)浪費(fèi)了無(wú)數(shù)時(shí)間,只是玩玩和玩得開(kāi)心。

不要相信我的話(huà)——著名的荷蘭印象派畫(huà)家文森特梵高說(shuō),“我有時(shí)認(rèn)為沒(méi)有什么比繪畫(huà)更令人愉快的了?!?/p>

我想他是在做某事!

不管怎樣,我希望你能以開(kāi)放的心態(tài)對(duì)待接下來(lái)的幾天。也許你想跟隨編碼(我希望你這樣做!),或者你可能只是想坐下來(lái)看看有什么可能——無(wú)論哪種方式,我想你都會(huì)對(duì) SwiftUI 的繪圖的智能程度印象深刻!

今天你有四個(gè)主題要完成,你將在其中學(xué)習(xí)路徑、形狀、可插入形狀等。

繪圖:簡(jiǎn)介

在這個(gè)技術(shù)項(xiàng)目中,我們將仔細(xì)研究 SwiftUI 中的繪圖,包括創(chuàng)建自定義路徑和形狀、為你的更改設(shè)置動(dòng)畫(huà)、解決性能問(wèn)題等等——這是一個(gè)非常大的話(huà)題,值得密切關(guān)注。

在后臺(tái),SwiftUI 使用我們?cè)谄渌?Apple 框架上使用的相同繪圖系統(tǒng):Core Animation 和 Metal。大多數(shù)時(shí)候 Core Animation 負(fù)責(zé)我們的繪圖,無(wú)論是自定義路徑和形狀還是 UI 元素TextField,但當(dāng)事情真的變得復(fù)雜時(shí),我們可以向下移動(dòng)到 Metal——Apple 的低級(jí)框架,它針對(duì)復(fù)雜的繪圖進(jìn)行了優(yōu)化。SwiftUI 的一個(gè)巧妙特性是這兩者幾乎可以互換:我們可以通過(guò)一個(gè)小的改變從 Core Animation 轉(zhuǎn)移到 Metal。

不管怎樣,我們有很多內(nèi)容要講,所以請(qǐng)創(chuàng)建一個(gè)名為 Drawing 的新 App 項(xiàng)目,讓我們深入了解……

使用 SwiftUI 創(chuàng)建自定義路徑

SwiftUI 為我們提供了一個(gè)專(zhuān)門(mén)用于繪制自定義形狀的類(lèi)型Path。它的級(jí)別非常低,我的意思是你通常希望將它包裝在其他東西中以使其更有用,但由于它是其他工作的基礎(chǔ)構(gòu)建塊,我們將從那里開(kāi)始。

就像顏色、漸變和形狀一樣,路徑本身就是視圖。這意味著我們可以像使用文本視圖和圖像一樣使用它們,盡管你會(huì)看到它有點(diǎn)笨拙。

讓我們從一個(gè)簡(jiǎn)單的形狀開(kāi)始:畫(huà)一個(gè)三角形。有幾種創(chuàng)建路徑的方法,包括一種接受繪圖指令閉包的方法。這個(gè)閉包必須接受一個(gè)參數(shù),這是繪制的路徑。我意識(shí)到一開(kāi)始這可能有點(diǎn)費(fèi)腦筋,因?yàn)槲覀冋趧?chuàng)建一個(gè)路徑,并且在我們正在傳遞的路徑的初始化器內(nèi)部繪制路徑,但可以這樣想:SwiftUI給我們創(chuàng)建了一個(gè)空的路徑,然后讓我們有機(jī)會(huì)盡可能多地添加它。

Paths 有很多方法可以創(chuàng)建正方形、圓形、弧形和直線(xiàn)形狀。對(duì)于我們的三角形,我們需要移動(dòng)到一個(gè)起始位置,然后添加如下三行:

我們以前沒(méi)有用過(guò)CGPoint,但我確實(shí)在項(xiàng)目 6 中偷偷對(duì)CGSize做了一個(gè)快速參考?!癈G”是 Core Graphics 的縮寫(xiě),它提供了一系列基本類(lèi)型,讓我們可以參考 X/Y 坐標(biāo) (?CGPoint)、寬度和高度 (?CGSize) 和矩形框 (?CGRect)。

當(dāng)我們的三角形代碼運(yùn)行時(shí),你會(huì)看到一個(gè)大的黑色三角形。你看到它相對(duì)于屏幕的位置取決于你使用的是什么模擬器,這是這些原始路徑問(wèn)題的一部分:我們需要使用精確的坐標(biāo),所以如果你想單獨(dú)使用路徑,你要么需要接受GeometryReader在所有設(shè)備上調(diào)整大小或使用類(lèi)似的東西來(lái)相對(duì)于它們的容器縮放它們。

我們很快就會(huì)看到一個(gè)更好的選擇,但首先讓我們看看為路徑著色。一種選擇是使用fill()修飾符,如下所示:

我們還可以使用stroke()修飾符在路徑周?chē)L制而不是填充它:

不過(guò),這看起來(lái)不太正確——我們?nèi)切蔚牡捉呛芷炼液茕h利,但頂角壞了。發(fā)生這種情況是因?yàn)?SwiftUI 確保線(xiàn)條與前后的內(nèi)容整齊地連接起來(lái),而不僅僅是一系列單獨(dú)的線(xiàn)條,但我們的最后一行后面沒(méi)有任何內(nèi)容,因此無(wú)法建立連接。

解決此問(wèn)題的一種方法是要求 SwiftUI 關(guān)閉子路徑,這是我們?cè)诼窂街欣L制的形狀:

另一種方法是使用 SwiftUI 的專(zhuān)用StrokeStyle結(jié)構(gòu),它使我們能夠控制每條線(xiàn)應(yīng)如何連接到它之后的線(xiàn)(線(xiàn)連接),以及當(dāng)它結(jié)束后沒(méi)有連接時(shí)應(yīng)如何繪制每條線(xiàn)(線(xiàn)帽)。這特別有用,因?yàn)?join 和 cap 的選項(xiàng)之一是.round,它創(chuàng)建了柔和的圓形:

有了它,你就可以刪除對(duì) path.closeSubpath()的調(diào)用,因?yàn)樗辉傩枰恕?/p>

使用圓角解決了我們邊緣粗糙的問(wèn)題,但是并沒(méi)有解決固定坐標(biāo)的問(wèn)題。為此,我們需要從路徑繼續(xù)前進(jìn),看看更復(fù)雜的東西:形狀。

SwiftUI 中的路徑與形狀

SwiftUI 支持使用兩種略有不同的類(lèi)型進(jìn)行自定義繪圖:路徑和形狀。路徑是一系列的繪圖指令,例如“從這里開(kāi)始,到這里畫(huà)一條線(xiàn),然后在那里畫(huà)一個(gè)圓”,都是使用絕對(duì)坐標(biāo)。相比之下,形狀不知道將在哪里使用或?qū)⑹褂枚啻?,而是要求將其自身繪制在給定的矩形內(nèi)。

有用的是,形狀是使用路徑構(gòu)建的,所以一旦你理解了路徑,形狀就很容易了。此外,就像路徑、顏色和漸變一樣,形狀是視圖,這意味著我們可以將它們與文本視圖、圖像等一起使用。

SwiftUI 實(shí)現(xiàn)為具有單一必需方法的Shape協(xié)議:給定以下矩形,你想繪制什么路徑?這仍然會(huì)像直接使用原始路徑一樣創(chuàng)建和返回路徑,但是因?yàn)槲覀円呀?jīng)掌握了形狀將被使用的大小,所以我們確切地知道要繪制我們的路徑有多大——我們不再需要依賴(lài)固定坐標(biāo)。

例如,之前我們使用Path創(chuàng)建了一個(gè)三角形,但我們可以將其包裹在一個(gè)形狀中以確保它自動(dòng)占據(jù)所有可用空間,如下所示:

使這項(xiàng)工作變得容易得多CGRect,它提供了有用的屬性,例如minX(矩形中的最小 X 值)、maxX(矩形中的最大 X 值)和midXminXmaxX之間的中點(diǎn))。

然后我們可以創(chuàng)建一個(gè)精確大小的紅色三角形,如下所示:

StrokeStyle形狀還支持用于創(chuàng)建更高級(jí)筆畫(huà)的相同參數(shù):

理解PathShape之間區(qū)別的關(guān)鍵是可重用性:路徑旨在完成一件特定的事情,而形狀具有繪圖空間的靈活性,并且還可以接受參數(shù)以讓我們進(jìn)一步自定義它們。

為了演示這一點(diǎn),我們可以創(chuàng)建一個(gè)Arc接受三個(gè)參數(shù)的形狀:開(kāi)始角度、結(jié)束角度以及是否順時(shí)針繪制圓弧。這可能看起來(lái)很簡(jiǎn)單,特別是因?yàn)?span id="s0sssss00s" class="color-pink-02">Path它有一個(gè)addArc()方法,但正如你將看到的那樣,它有幾個(gè)有趣的雜項(xiàng)。

讓我們從最簡(jiǎn)單的弧形開(kāi)始:

我們現(xiàn)在可以像這樣創(chuàng)建一個(gè)圓弧:

如果你查看弧線(xiàn)的預(yù)覽,很可能它看起來(lái)與你預(yù)期的完全不同。我們要求順時(shí)針旋轉(zhuǎn)從 0 度到 110 度的弧,但我們似乎得到了逆時(shí)針旋轉(zhuǎn)的 90 度到 200 度的弧。

這里發(fā)生的事情有兩個(gè)方面:

  1. 在 SwiftUI 看來(lái) 0 度不是筆直向上,而是筆直向右。

  2. 形狀從左下角而不是左上角測(cè)量它們的坐標(biāo),這意味著 SwiftUI 從一個(gè)角度到另一個(gè)角度是相反的。在我看來(lái),這是非常陌生的。

我們可以使用一種新方法來(lái)解決這兩個(gè)問(wèn)題,該path(in:)方法從開(kāi)始角和結(jié)束角減去 90 度,并翻轉(zhuǎn)方向,以便 SwiftUI 的行為符合自然預(yù)期的方式:

運(yùn)行該代碼,看看你的想法——對(duì)我來(lái)說(shuō),它產(chǎn)生了一種更自然的工作方式,并巧妙地隔離了 SwiftUI 的繪圖行為。


使用 InsettableShape 添加 strokeBorder() 支持

如果你創(chuàng)建一個(gè)沒(méi)有特定大小的形狀,它會(huì)自動(dòng)擴(kuò)展以占據(jù)所有可用空間。例如,這將創(chuàng)建一個(gè)填滿(mǎn)我們視圖的圓圈,并給它一個(gè) 40 磅的藍(lán)色邊框:

仔細(xì)觀察邊框的左右邊緣——你是否注意到它們是如何被切斷的?

你在這里看到的是 SwiftUI 在形狀周?chē)L制邊框的方式的副作用。如果你遞給某人一個(gè)圓的鉛筆輪廓,并要求他們用粗筆在圓上畫(huà)畫(huà),他們會(huì)準(zhǔn)確地描繪出圓的線(xiàn)——大約一半的筆在線(xiàn)內(nèi),一半在線(xiàn)外。這就是 SwiftUI 為我們所做的,但是當(dāng)我們的形狀到達(dá)屏幕邊緣時(shí),這意味著邊框的外部部分最終超出了我們的屏幕邊緣。

現(xiàn)在嘗試使用這個(gè)圓圈:

現(xiàn)在我們把stroke()改成strokeBorder(),得到了一個(gè)更好的結(jié)果:我們所有的邊界都是可見(jiàn)的,因?yàn)?Swift 撫摸著圓圈的內(nèi)部而不是在線(xiàn)的中心。

之前我們構(gòu)建了一個(gè)這樣的Arc形狀:

就像Circle,它會(huì)自動(dòng)占用所有可用空間。但是,這種代碼將不起作用:

如果你打開(kāi) Xcode 的錯(cuò)誤消息,你會(huì)看到它說(shuō)“Value of type 'Arc' has no member 'strokeBorder’(類(lèi)型 'Arc' 的值沒(méi)有成員 'strokeBorder')”——也就是說(shuō),strokeBorder()修飾符不存在于Arc.

SwiftUI的Circle和我們的Arc之間有一個(gè)很小但很重要的區(qū)別:兩者都符合Shape協(xié)議,但Circle?也符合協(xié)議:InsettableShape.?這是一種可以插入(向內(nèi)縮?。┮欢恳援a(chǎn)生另一種形狀的形狀。它生成的內(nèi)嵌形狀可以是任何其他類(lèi)型的不可設(shè)置形狀,但實(shí)際上它應(yīng)該是相同的形狀,只是較小的矩形。

為了讓Arc符合InsettableShape。我們需要向它添加一個(gè)額外的方法:inset(by:)。這將被賦予插入量(筆劃線(xiàn)寬的一半),并且應(yīng)該返回一種新的可插入形狀——在我們的例子中,這意味著我們應(yīng)該創(chuàng)建一個(gè)插入弧。問(wèn)題是,我們不知道弧的實(shí)際大小,因?yàn)?span id="s0sssss00s" class="color-pink-02">path(in:)還沒(méi)有被調(diào)用。

解決方案其實(shí)很簡(jiǎn)單:如果我們給Arc形狀一個(gè)insetAmount默認(rèn)為 0 的新屬性,我們可以在inset(by:)調(diào)用時(shí)添加它。需要時(shí),我們可以調(diào)用多次inset(by:),例如,如果我們想手動(dòng)調(diào)用一次,然后使用strokeBorder().

首先,將這個(gè)新屬性添加到Arc

現(xiàn)在給它這個(gè)inset(by:)方法:

重要提示:這是我們需要使用CGFloat的極少數(shù)地方之一,這是一種古老的Double形式,有點(diǎn)奇怪,它已經(jīng)進(jìn)入了 SwiftUI。它也被用于許多其他地方,但大多數(shù)情況下 Swift 允許我們使用Double替代它!

傳入的amount參數(shù)應(yīng)應(yīng)用于所有邊,在弧的情況下,這意味著我們應(yīng)該使用它來(lái)減小繪制半徑。因此,將addArc()內(nèi)部調(diào)用更改path(in:)為:

有了這個(gè)改變,我們現(xiàn)在可以像這樣Arc符合InsettableShape

注意:?InsettableShape實(shí)際上是建立在 Shape之上的,因此無(wú)需在其中添加兩者。


SwiftUI學(xué)習(xí)100天(Day43 - 項(xiàng)目 9,第一部分)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
咸阳市| 高淳县| 桑植县| 苏州市| 平和县| 邵阳县| 高唐县| 奉贤区| 黑水县| 洞头县| 柳林县| 庆云县| 永登县| 调兵山市| 曲水县| 大埔区| 遵义市| 西平县| 东乡县| 罗山县| 抚宁县| 满洲里市| 舒城县| 炉霍县| 哈尔滨市| 卫辉市| 沙田区| 监利县| 富阳市| 珠海市| 册亨县| 烟台市| 桃园市| 德清县| 黄梅县| 仲巴县| 西和县| 正镶白旗| 丰台区| 阿克陶县| 柘荣县|