#9 Xcode — 使用圖片/文字/emoji,加入邊框 & 圓角製作漂亮卡片

目錄

⦿ 去背
⦿ scaleAspectFit
⦿ 加入美美的畫面
⦿ Emoji
⦿ 不演了

去背

在 MAC 的預覽程式中,我們可以點擊右上角的 show Markup toolbar,再透過左上角的魔術棒去幫圖片去背:

在 Playground 中,生成 ImageView,將圖片放進去後會呈現如下:

維尼被加入歐巴馬後,我們可以看到圖片呈現青色,但維尼卻不見了,這不代表維尼沒有被加進去,是加進去了,但呈現的範圍不正確,調整如下:

bearImageView.frame = obamaImageView.frame

如此一來,維尼就正常出現如下:

但由於寬度比例不一樣,維尼是比較瘦高的比例,所以此時歐巴馬的骨架更顯瘦了,我們試著切換兩張圖片的層級,跳出錯誤如下:

你總不能以你泥中有我,我泥中有你的概念來去改變圖片的 hierarchy,就好比 memory leak 是發生在 ARC 下,當兩個變數互相參考,即便釋放掉,最後記憶體也沒有空出來,造成記憶體空間越來越小。

不過在你正確把歐巴馬加到維尼身上後,沒去背的歐巴馬會完全擋住維尼。

scaleAspectFit

若希望歐巴馬正常顯示,會操作如下:

希望圖片的 scale 是維持它本來的比例,我們設定 Image View 的 contentMode 為 scaleAspectFit。

繼續閱讀|回目錄

加入美美的畫面

接著到專案裡,將圖片的大小設定為略小於螢幕寬度,並讓圖片置中。

右邊的預覽圖是在 UIKit 中,使用 UIViewControllerRepresentable,並實作兩個 function:makeUIViewController、updateUIViewController,接著就可以加入 ViewControllerView 來進行預覽了:

struct ViewControllerView_Previews: PreviewProvider {
static var previews: some View {
ViewControllerView()
.previewDevice("iPhone 11 Pro")
}
}

不過預覽的這個置中看起來不科學,等到 build 時看到如下:

正常了!幫這張照片加入方框讓它變成像框,不過顏色這時就很重要了,一不小心可能會像遺照。

接著調整透明度 .alpha 為 0.7,以免將來加入的 Emoji 不明顯,好了!前置作業完成。

繼續閱讀|回目錄

Emoji

var someLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
someLabel.font = UIFont.systemFont(ofSize: 50)
someLabel.text = "🇨🇳"

參考下面文章。

要讓 Emoji 位移跟縮放,最後圍繞在照片四周,我們會用到 CGAffineTransform 如下:

        someLabel.transform = 
CGAffineTransform(translationX: 10, y: 20)
someLabel.transform = CGAffineTransform.identity.translatedBy(x: 10, y: 20).scaledBy(x: 1.5, y: 1.5) someLabel.transform =
CGAffineTransform(rotationAngle: someDegree * 45)
someLabel.transform = CGAffineTransform.identity.rotated(by: someDegree * 90).scaledBy(x: 1.5, y: 1.5)
someLabel.transform = CGAffineTransform.identity.scaledBy(x: 1.5, y: 1.5).translatedBy(x: 10, y: 20)

Affine Transform,仿射變換,是在幾何中對圖像做各種移動,放大、縮小的處理,原理應是線性代數所謂的特徵值(Eigen Value)。

呼叫 CGAffineTranform,更改裡面的參數,此時只能做到位移、旋轉在同一行的處理,若想一起處理的話會這樣操作:CGAffineTransform.identity.translatedBy(x:y:).scaleBy(x:y:).rotated(by: someDegree * 90)
一般來說,先位移、縮放,再去做旋轉的動作,比較容易做 rendering 的追蹤、管控。

當我們將 Emoji 做為素材,就可用跑迴圈的方式去做到仿射變換,複製多個 Emoji 素材,讓它最終環繞在像框四周,如下:

雖然可以透過 CGAffineTransform.identity 去做仿射變換的連續處理,但這樣一來程式碼就會變得不太容易讀,我們透過 extension UIView 增加一些 function 如下:

extension UIView {
func translatedBy(x: CGFloat, y: CGFloat) {
self.transform = self.transform.translatedBy(x: x, y: y)
}

func scaledBy(x: CGFloat, y: CGFloat) {
self.transform = self.transform.scaledBy(x: x, y: y)
}

func rotated(by angle: CGFloat) {
self.transform = self.transform.rotated(by: angle)
}
}

接著程式碼就可以進一步優化為:

        let aDegree = CGFloat.pi / 180
var count = 0

for i in 1...5 {
for j in 1...5 {
if i == 1 || i == 5 || j == 1 || j == 5 {

count = count + 4
emojiLabel = UILabel(frame: CGRect(x: -50,
y: -60,
width: 30,
height: 30))
emojiLabel.text = "🇨🇳"
obamaImgView.addSubview(emojiLabel)

emojiLabel.translatedBy(
x: (obamaImgView.bounds.width / 5) * CGFloat(i),
y: (obamaImgView.bounds.height / 5) * CGFloat(j)
)

emojiLabel.scaledBy(x: 1.5, y: 1.5)

emojiLabel.rotated(by: (aDegree * 11.25 * CGFloat(count)))
}
}
}

成果如下:

原圖皆來自網路,著作權為原著所有。

如果要說初衷是仿製賈伯斯在時代雜誌的封面的話,是否有點說不過去呀?還是我真沒有什麼美術天份。

不演了

既然都擺入中國國旗了,換張照片進去也不爲過吧。

這次就分享到這,感謝您的閱讀。

繼續閱讀|回目錄

附上 GitHub:

--

--

Chun-Li 春麗
彼得潘的 Swift iOS / Flutter App 開發教室

Do not go gentle into that good night, Old age should burn and rave at close of day; Rage, rage, against the dying of the light.