亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

iOS開發(fā)UI之弧形文字

 更新時間:2022年07月20日 16:28:43   作者:MichaelJackchuang  
這篇文章主要為大家詳細介紹了iOS開發(fā)UI之弧形文字,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了iOS開發(fā)UI之弧形文字的具體代碼,供大家參考,具體內容如下

要實現(xiàn)類似效果的弧形文字,網上找了一圈沒找到有簡單的實現(xiàn)方式,CATextLayer也不能使用path來用路徑繪制出來,所以我采用了一個曲線救國的方式。

實現(xiàn)思路

1.先找到文字的中心點 ,用一段圓弧將這些中心點連接起來

2.過每個中心點做圓弧的切線,找到圓弧的圓點O,連接O與每個中心點

3.現(xiàn)在把字去掉,來找點

圓點為O,圓弧最左邊為A,最右邊為B,頂點為N,AB與OP交點為P,由圓的垂徑定理可以知道,AB是垂直于OP的。現(xiàn)在設AB長度為w,NP長度為h,OA、OA都是圓的半徑,長度為r,則OP為r-h。將圓弧上面部分用一個矩形包起來,這個就可以作為顯示弧形文字的view,如圖。

由圖中可以知道△AOP是直角三角形,根據勾股定理,則有r²=(w/2)²+(r-h)²,可以知道r=h/2+w²/8h,h是view的height,w是view的width,這兩個是已知條件,所以可以得到圓的半徑r。
假設弧形文字只有3個字,那么這三個字就分別在A、N、B的位置上,現(xiàn)在△AOP的三邊都是已知的,那么可以求角AOP的角度α,用反三角函數(shù)arcsin或者arccos,則可以獲得α的具體值。這個角α就是每個夾角的角度,弧形文字長度不固定時計算方式同理。

4.計算每個點的位置坐標

以view的左上角為原點(0,0),那么圓點O的坐標就是(w/2,r)。如果以圓點O為直角坐標系圓點,那么頂點N的起始弧度就是-π/2,將其設為startAngle。其他每個點的坐標就是(rcos(startAngle+αi),rsin(startAngle+αi)),其中i是每個點的索引(從0開始)。再將其轉換到view左上角是原點的坐標系,則坐標為(w/2+rcos(startAngle+αi),r+rsin(startAngle+αi)),就是x和y分別加上圓點O的x和y。

代碼實現(xiàn)

1.定義一些變量

var textLength:Int = 0 // 文字長度
var viewWidth:CGFloat = 0 // view寬度
var viewHeight:CGFloat = 0 // view高度
var arcRadius:CGFloat = 0 // 圓半徑
var textHeight:CGFloat = 20 // 文字高度
var totalRadian:CGFloat = 0 // 總弧度
var eachRadian:CGFloat = 0 // 每個夾角弧度

2.初始化變量

viewWidth = view.frame.size.width - textHeight * 2
viewHeight = view.frame.size.height - textHeight
arcRadius = viewHeight / 2 + viewWidth * viewWidth / 8 / viewHeight // 根據垂徑定理得到
textLength = text.isEmpty ? 1 : text.count
totalRadian = ?asin(viewWidth / 2 / arcRadius) * 2 // 用反三角函數(shù)求角度,乘2之前得到的是一半的角度,乘2得到總角度(弧度制)
eachRadian = totalRadian / (CGFloat(textLength) - 1)

3.找點顯示文字

// 先移除之前創(chuàng)建的
view.subviews.forEach { (subview) in
? ? subview.removeFromSuperview()
}

let startAngle:CGFloat = -CGFloat.pi / 2 - totalRadian / 2 // 起始角度,從左到右,取第一個字符的位置為起始角度

for i in 0..<textLength {
? ? let angle = startAngle + eachRadian * CGFloat(i)
? ? let x:CGFloat = arcRadius * cos(angle)
? ? let y:CGFloat = arcRadius * sin(angle)
? ? let center = CGPoint(x: frame.size.width / 2 + x, y: arcRadius + textHeight + y) // 各個label中點坐標
? ??
? ? if text.isEmpty {return}
? ? let label = UILabel()
? ? label.textColor = .black
? ? label.font = UIFont.systemFont(ofSize: 15)
? ? let character:Character = text[text.index(text.startIndex, offsetBy: i)] // 獲取對應索引位置上的字符
? ? label.text = String(character)
? ? label.sizeToFit()
? ? label.center = center
? ? view.addSubview(label)
}

此時,繪制出來的文字方向還是正的,沒有發(fā)生偏轉

我們需要分別將每個文字旋轉一定的角度。在最頂點N的文字的角度是正的,沒有發(fā)生偏轉,那么我們就以N點文字為基準點,經過觀察論證,每個文字的旋轉角度和每個點與圓心O的連線和線段ON形成的夾角一致,即eachRadian*i - totalRadian / 2。

4.旋轉文字

let alpha = angle + CGFloat.pi / 2 // 這里的angle和上面循環(huán)里的是同一個變量
label.transform = CGAffineTransform(rotationAngle: alpha)

至此,基本實現(xiàn)了弧形文字的效果。不過還是有點問題,當文字較少時,文字之間的間隙很大

為了解決這個問題,我們可以給每個夾角設置一個固定值

5.固定夾角值

eachRadian = 0.1 // 0.85 // 此處是弧度值 ,可以任意一個角度,0.1弧度約為5.7度
totalRadian = eachRadian * (CGFloat(textLength) - 1)

最后,在不設置固定角度時,為了不讓每次文字的開始結束都在view的最下邊開始,可以將totalRadian乘以一個小于1的值,來減小角度。

totalRadian = ?asin(viewWidth / 2 / arcRadius) * 2 * 4 / 5

6.用CATextLayer

如果覺得UILbel占用資源更大的話,可以考慮用更輕量級的CATextLayer

let textLayer = CATextLayer()
textLayer.bounds = CGRect(x: 0, y: 0, width: 20, height: 20)
let character:Character = text[text.index(text.startIndex, offsetBy: i)]
textLayer.string = String(character)
textLayer.foregroundColor = UIColor.black.cgColor
textLayer.font = UIFont.systemFont(ofSize: 15)
textLayer.fontSize = 15
textLayer.alignmentMode = .center
textLayer.contentsScale = UIScreen.main.scale
textLayer.position = center
view.layer.addSublayer(textLayer)

// 旋轉
let alpha = angle + CGFloat.pi / 2
let trans = CATransform3DIdentity
textLayer.transform = CATransform3DRotate(trans, alpha, 0, 0, 1)

實現(xiàn)的效果是一樣的。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論