iOS開發(fā)UI之弧形文字
本文實(shí)例為大家分享了iOS開發(fā)UI之弧形文字的具體代碼,供大家參考,具體內(nèi)容如下
要實(shí)現(xiàn)類似效果的弧形文字,網(wǎng)上找了一圈沒找到有簡(jiǎn)單的實(shí)現(xiàn)方式,CATextLayer也不能使用path來用路徑繪制出來,所以我采用了一個(gè)曲線救國(guó)的方式。
實(shí)現(xiàn)思路
1.先找到文字的中心點(diǎn) ,用一段圓弧將這些中心點(diǎn)連接起來
2.過每個(gè)中心點(diǎn)做圓弧的切線,找到圓弧的圓點(diǎn)O,連接O與每個(gè)中心點(diǎn)
3.現(xiàn)在把字去掉,來找點(diǎn)
圓點(diǎn)為O,圓弧最左邊為A,最右邊為B,頂點(diǎn)為N,AB與OP交點(diǎn)為P,由圓的垂徑定理可以知道,AB是垂直于OP的?,F(xiàn)在設(shè)AB長(zhǎng)度為w,NP長(zhǎng)度為h,OA、OA都是圓的半徑,長(zhǎng)度為r,則OP為r-h。將圓弧上面部分用一個(gè)矩形包起來,這個(gè)就可以作為顯示弧形文字的view,如圖。
由圖中可以知道△AOP是直角三角形,根據(jù)勾股定理,則有r²=(w/2)²+(r-h)²,可以知道r=h/2+w²/8h,h是view的height,w是view的width,這兩個(gè)是已知條件,所以可以得到圓的半徑r。
假設(shè)弧形文字只有3個(gè)字,那么這三個(gè)字就分別在A、N、B的位置上,現(xiàn)在△AOP的三邊都是已知的,那么可以求角AOP的角度α,用反三角函數(shù)arcsin或者arccos,則可以獲得α的具體值。這個(gè)角α就是每個(gè)夾角的角度,弧形文字長(zhǎng)度不固定時(shí)計(jì)算方式同理。
4.計(jì)算每個(gè)點(diǎn)的位置坐標(biāo)
以view的左上角為原點(diǎn)(0,0),那么圓點(diǎn)O的坐標(biāo)就是(w/2,r)。如果以圓點(diǎn)O為直角坐標(biāo)系圓點(diǎn),那么頂點(diǎn)N的起始弧度就是-π/2,將其設(shè)為startAngle。其他每個(gè)點(diǎn)的坐標(biāo)就是(rcos(startAngle+αi),rsin(startAngle+αi)),其中i是每個(gè)點(diǎn)的索引(從0開始)。再將其轉(zhuǎn)換到view左上角是原點(diǎn)的坐標(biāo)系,則坐標(biāo)為(w/2+rcos(startAngle+αi),r+rsin(startAngle+αi)),就是x和y分別加上圓點(diǎn)O的x和y。
代碼實(shí)現(xiàn)
1.定義一些變量
var textLength:Int = 0 // 文字長(zhǎng)度 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 // 每個(gè)夾角弧度
2.初始化變量
viewWidth = view.frame.size.width - textHeight * 2 viewHeight = view.frame.size.height - textHeight arcRadius = viewHeight / 2 + viewWidth * viewWidth / 8 / viewHeight // 根據(jù)垂徑定理得到 textLength = text.isEmpty ? 1 : text.count totalRadian = ?asin(viewWidth / 2 / arcRadius) * 2 // 用反三角函數(shù)求角度,乘2之前得到的是一半的角度,乘2得到總角度(弧度制) eachRadian = totalRadian / (CGFloat(textLength) - 1)
3.找點(diǎn)顯示文字
// 先移除之前創(chuàng)建的 view.subviews.forEach { (subview) in ? ? subview.removeFromSuperview() } let startAngle:CGFloat = -CGFloat.pi / 2 - totalRadian / 2 // 起始角度,從左到右,取第一個(gè)字符的位置為起始角度 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) // 各個(gè)label中點(diǎn)坐標(biāo) ? ?? ? ? 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)] // 獲取對(duì)應(yīng)索引位置上的字符 ? ? label.text = String(character) ? ? label.sizeToFit() ? ? label.center = center ? ? view.addSubview(label) }
此時(shí),繪制出來的文字方向還是正的,沒有發(fā)生偏轉(zhuǎn)
我們需要分別將每個(gè)文字旋轉(zhuǎn)一定的角度。在最頂點(diǎn)N的文字的角度是正的,沒有發(fā)生偏轉(zhuǎn),那么我們就以N點(diǎn)文字為基準(zhǔn)點(diǎn),經(jīng)過觀察論證,每個(gè)文字的旋轉(zhuǎn)角度和每個(gè)點(diǎn)與圓心O的連線和線段ON形成的夾角一致,即eachRadian*i - totalRadian / 2。
4.旋轉(zhuǎn)文字
let alpha = angle + CGFloat.pi / 2 // 這里的angle和上面循環(huán)里的是同一個(gè)變量 label.transform = CGAffineTransform(rotationAngle: alpha)
至此,基本實(shí)現(xiàn)了弧形文字的效果。不過還是有點(diǎn)問題,當(dāng)文字較少時(shí),文字之間的間隙很大
為了解決這個(gè)問題,我們可以給每個(gè)夾角設(shè)置一個(gè)固定值
5.固定夾角值
eachRadian = 0.1 // 0.85 // 此處是弧度值 ,可以任意一個(gè)角度,0.1弧度約為5.7度 totalRadian = eachRadian * (CGFloat(textLength) - 1)
最后,在不設(shè)置固定角度時(shí),為了不讓每次文字的開始結(jié)束都在view的最下邊開始,可以將totalRadian乘以一個(gè)小于1的值,來減小角度。
totalRadian = ?asin(viewWidth / 2 / arcRadius) * 2 * 4 / 5
6.用CATextLayer
如果覺得UILbel占用資源更大的話,可以考慮用更輕量級(jí)的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) // 旋轉(zhuǎn) let alpha = angle + CGFloat.pi / 2 let trans = CATransform3DIdentity textLayer.transform = CATransform3DRotate(trans, alpha, 0, 0, 1)
實(shí)現(xiàn)的效果是一樣的。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- iOS基于 UILabel實(shí)現(xiàn)文字添加描邊功能
- iOS中UILabel設(shè)置居上對(duì)齊、居中對(duì)齊、居下對(duì)齊及文字置頂顯示
- iOS如何將UIButton中的圖片與文字上下對(duì)齊詳解
- 詳解IOS 利用storyboard修改UITextField的placeholder文字顏色
- iOS改變UITextField占位文字顏色的三種方法
- iOS開發(fā)中Swift3 監(jiān)聽UITextView文字改變的方法(三種方法)
- IOS開發(fā)UIButton(左邊圖片右邊文字效果)
- iOS設(shè)置UIButton文字顯示位置和字體大小、顏色的方法
- iOS中的UITextView文字輸入光標(biāo)使用技巧小結(jié)
- iOS應(yīng)用中UILabel文字顯示效果的常用設(shè)置總結(jié)
相關(guān)文章
iOS APP實(shí)現(xiàn)微信H5支付示例總結(jié)
這篇文章主要介紹了iOS APP實(shí)現(xiàn)微信H5支付示例總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02iOS開發(fā)中UITableview控件的基本使用及性能優(yōu)化方法
這篇文章主要介紹了iOS開發(fā)中UITableview控件的基本使用及性能優(yōu)化方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-12-12cmake ios終端下執(zhí)行提示錯(cuò)誤 iOS version not found, tested: [5.0;5.1;6
這篇文章主要介紹了cmake ios終端下執(zhí)行提示錯(cuò)誤 iOS version not found, tested: [5.0;5.1;6.0;6.1;7.0;8.3]的解決方案的相關(guān)資料,需要的朋友可以參考下2016-10-10談?wù)刬OS開發(fā)之JSON格式數(shù)據(jù)的生成與解析
JSON格式取代了xml給網(wǎng)絡(luò)傳輸帶來了很大的便利,本篇文章主要介紹了iOS開發(fā):對(duì)象直接轉(zhuǎn)化成JSON詳解,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01