PM018兩種顯示方式的差異

UIView及CALayer

在畫各國國旗時,因為參考的來源有重覆用到很多類似的圖案,所以就順勢地朝位移、旋轉、縮放會用到的CGAffineTransform研究,結果寫了大半天沒有顯示錯誤,但圖案也顯示不出來;發現是型別的問題吧??但寫法也看不出有錯,後來直接貼他人寫好的也是一樣沒有顯示,甚至貼上chatgpt的還是一樣。所以我就去睡覺了,醒來後想到既然型別造成沒有顯示,那我直接用function產生calayer,再另外顯示出該layer!

所以這篇為研究後心得…

這張是使用CGAffineTransform 控制圖片的縮放、位移及旋轉。
在手機上執行
        // 圖片來源:pixababy。  主題:使用CGAffineTransform來位移、縮放、旋轉
let ghostView = UIImageView(image: UIImage(named: "ghost"))
let ghost2View = UIImageView(image: UIImage(named: "ghost"))
let ghostMirrorView = UIImageView(image: UIImage(named: "ghost"))

//縮放:兩種方式:1.直接套用縮放效果。 2.用呼叫的方式。
ghostView.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
view.addSubview(ghostView)

ghost2View.transform = CGAffineTransform.identity.scaledBy(x: 0.3, y: 0.3)
view.addSubview(ghost2View)

//檸檬來插花…
let lemonView = UIImageView(image: UIImage(named: "lemon"))
lemonView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5).translatedBy(x: 200, y: 200)
view.addSubview(lemonView)

//先變小且垂直鏡像→ 然後再向y軸位移100個單位→ 再將此圖的框架的x點加上框架的最大值加8單位,故可看出右邊壓在檸檬上方的小鬼是這裡執行後的結果。
ghostMirrorView.transform = CGAffineTransform.identity.scaledBy(x: -0.3, y: 0.3).translatedBy(x: 0, y: 100)
ghostMirrorView.frame.origin.x = ghostMirrorView.frame.maxX + 8
view.addSubview(ghostMirrorView)

//海鷗來旋轉
let rotateDegree = ( CGFloat.pi / 180 ) * 55
let seagull0View = UIImageView(image: UIImage(named: "seagull"))
seagull0View.transform = CGAffineTransform.identity.scaledBy(x: 0.4, y: 0.4).translatedBy(x: 100, y: 1300).rotated(by: rotateDegree)
view.addSubview(seagull0View)

let seagull1View = UIImageView(image: UIImage(named: "seagull"))
seagull1View.transform = CGAffineTransform.identity.scaledBy(x: 0.4, y: 0.4).translatedBy(x: 0, y: 1600)
view.addSubview(seagull1View)

雖然看起來都是顯示出圖案,但是用以顯示的方法不同,適用的地方也不同。※注意最後一行所用的view方法不一樣!

       //左下用貝茲產生三角形路徑(path), 型別是UIBezierPath
let path2: UIBezierPath = UIBezierPath()
path2.move(to: CGPoint(x: 20, y: 300))
path2.addLine(to: CGPoint(x: 80, y: 300))
path2.addLine(to: CGPoint(x: 50, y: 600))
path2.close()
//左下用CAShapeLayer上色,型別為CAShapeLayer
let shapLayer2: CAShapeLayer = CAShapeLayer()
shapLayer2.path = path2.cgPath //將貝茲產生的路徑複製並轉換成cgpath型別。//shapLayer內的path屬性為cgpath的型別
shapLayer2.fillColor = UIColor.blue.cgColor //shapLayer內的fillcolor屬性為cgcolor的型別
//最後使用UIView顯示出來。view是controller所管理的;layer是delegate;
//controller用代理載入這個CAShapeLayer型別的物件
view.layer.addSublayer(shapLayer2)

//calayer是屬於ca框架的一部份,輕量化用的、顯示圖形、動畫




//右下角使用UIView產生正方形的方塊。uiview是屬於用戶這塊的,互動使用。
let uiviewArea: UIView = UIView(frame: CGRect(x: 80, y: 600, width: 100, height: 100))
uiviewArea.backgroundColor = UIColor.gray
//controller直接顯示UIView型別的物件
view.addSubview(uiviewArea)

將貝茲所畫且calayer顯示的圖樣function化,就可以簡單的重覆利用。

簡單改造
        /////////使用function來產生尖頭朝上的綠色三角形
func theThingview () -> CAShapeLayer {
let path = UIBezierPath()
path.move(to: CGPoint(x: 200, y: 300))
path.addLine(to: CGPoint(x: 250, y: 250))
path.addLine(to: CGPoint(x: 300, y: 300))
path.close()
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.fillColor = UIColor.systemGreen.cgColor
return shapeLayer
}



view.layer.addSublayer(theThingview())


let anotherTing: CAShapeLayer = theThingview()
let mirrVar = CGAffineTransform(scaleX: 1.2, y: 1.2)
anotherTing.setAffineTransform(mirrVar)
view.layer.addSublayer(anotherTing)

let an02thing: CALayer = theThingview()
an02thing.setAffineTransform(CGAffineTransform(scaleX: 1.6, y: 1.9).translatedBy(x: -100, y: 60))
view.layer.addSublayer(an02thing)
帶參數
        /////////使用function來產生尖頭朝上的三角形
func theThingview (_ colorR: CGFloat = 130,_ colorG: CGFloat = 30,_ colorB:CGFloat = 10) -> CAShapeLayer {
let path = UIBezierPath()
path.move(to: CGPoint(x: 200, y: 300))
path.addLine(to: CGPoint(x: 250, y: 250))
path.addLine(to: CGPoint(x: 300, y: 300))
path.close()
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.fillColor = CGColor(red: colorR/255, green: colorG/255, blue: colorB/255, alpha: 1)
return shapeLayer
}

//產生並顯示第一個三角形,顏色為預設:130/255。
view.layer.addSublayer(theThingview())

//產生並顯示第二個三角形,並且縮放倍率為:1.2。顏色為200/255
let anotherTing: CAShapeLayer = theThingview(200,200,200)
let mirrVar = CGAffineTransform(scaleX: 1.2, y: 1.2)
anotherTing.setAffineTransform(mirrVar)
view.layer.addSublayer(anotherTing)

//產生並顯示第三個三角形,並且縮放倍率為1.6,且往左移100,下移60。
let an02thing: CALayer = theThingview(20,80,200)
an02thing.setAffineTransform(CGAffineTransform(scaleX: 1.6, y: 1.9).translatedBy(x: -100, y: 60))
view.layer.addSublayer(an02thing)

一直找不到為何別人可以用uiview直接讓function可以return圖案並顯示,

所以再看了一下上課影片,以及投影片的例子,發現我一直卡在return這個觀點;其實不需要return某東西回去,直接顯示就好啦!

然後為何別人可以,而我無法顯示的原因是…

並未使用即時預覽來看,而是直接用模擬器或是手機上來確認的。

花了一些時間重新畫上新的星星。
關於用鏡像畫出星星
        func newStar(_ X: CGFloat,_ Y: CGFloat) {
let drawStarR = UIBezierPath()
let orgX = 0
let orgY = 0
drawStarR.move(to: CGPoint(x: orgX, y: orgY))
drawStarR.addLine(to: CGPoint(x: 22, y: 69))
drawStarR.addLine(to: CGPoint(x: 95, y: 69))
drawStarR.addLine(to: CGPoint(x: 36, y: 112))
drawStarR.addLine(to: CGPoint(x: 59, y: 181))
drawStarR.addLine(to: CGPoint(x: 0, y: 138))

let showStarR = CAShapeLayer()
showStarR.path = drawStarR.cgPath
showStarR.fillColor = CGColor(red: 0.3, green: 0.3, blue: 0.3, alpha: 1)
showStarR.lineWidth = 3
showStarR.strokeColor = CGColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 1)

let showStarL = CAShapeLayer()
showStarL.path = drawStarR.cgPath
showStarL.fillColor = showStarR.fillColor
showStarL.strokeColor = showStarR.strokeColor
showStarL.lineWidth = showStarR.lineWidth

let boundingBox = drawStarR.cgPath.boundingBox
showStarL.bounds = boundingBox
showStarL.position = CGPoint(x: boundingBox.midX, y: boundingBox.midY)

let putingRtoR = CGAffineTransform(translationX: X - CGFloat(integerLiteral: orgX), y: Y - CGFloat(integerLiteral: orgY))
showStarR.setAffineTransform(putingRtoR)
let putingLtoR = CGAffineTransform(scaleX: -1, y: 1).translatedBy(x: boundingBox.width - X + CGFloat(integerLiteral: orgX) , y: Y - CGFloat(integerLiteral: orgY) )
showStarL.setAffineTransform(putingLtoR)
view.layer.addSublayer(showStarL)
view.layer.addSublayer(showStarR)
}

newStar(10,30)
newStar(260,320)
newStar(293, 123)
newStar(183, 480)

參考來源:

https://www.geogebra.org/calculator

https://www.youtube.com/watch?v=TvCMww6zhzg

20231102

--

--