iOS UIVIEW弧形邊框

因項(xiàng)目需要使用弧形邊框UIView, 記錄一下加深記憶

效果圖
1540372936976.jpg
分析圖
1540373845168.jpg

分析

根據(jù)學(xué)習(xí)過的定理, 有如下前提:
過兩點(diǎn)的圓, 圓心在兩點(diǎn)連線的垂直平分線上
∠de = ∠bc
c^2 = a^2 + b^2
sin_bc = a / c;

a: 底部弧度的高度
b: view寬度的一半
Sin(de) = Sin(bc) = (c / 2) / d

以上可以算出半徑:
d = c / ( sin_bc * 2)

畫圓

右側(cè)藍(lán)點(diǎn)為起點(diǎn), 左側(cè)藍(lán)點(diǎn)為終點(diǎn)

藍(lán)點(diǎn)距圓心水平線高度為:
s1 = d - a
可得出起點(diǎn)弧度為:
rs = asin((s1) / d);
終點(diǎn)弧度為:
re = M_PI - rs

代碼

// .h

typedef NS_ENUM(NSInteger, DXRadianDirection) {
    DXRadianDirectionBottom     = 0,
    DXRadianDirectionTop        = 1,
    DXRadianDirectionLeft       = 2,
    DXRadianDirectionRight      = 3,
};
@interface DXRadianLayerView : UIView
// 圓弧方向, 默認(rèn)在下方
@property (nonatomic) DXRadianDirection direction;
// 圓弧高/寬, 可為負(fù)值。 正值凸, 負(fù)值凹
@property (nonatomic) CGFloat radian;
@end

// .m


@implementation DXRadianLayerView

- (void)setRadian:(CGFloat) radian
{
   if(radian == 0) return;
    CGFloat t_width = CGRectGetWidth(self.frame); // 寬
    CGFloat t_height = CGRectGetHeight(self.frame); // 高
    CGFloat height = fabs(radian); // 圓弧高度
    CGFloat x = 0;
    CGFloat y = 0;
    
    // 計(jì)算圓弧的最大高度
    CGFloat _maxRadian = 0;
    switch (self.direction) {
        case DXRadianDirectionBottom:
        case DXRadianDirectionTop:
            _maxRadian =  MIN(t_height, t_width / 2);
            break;
        case DXRadianDirectionLeft:
        case DXRadianDirectionRight:
            _maxRadian =  MIN(t_height / 2, t_width);
            break;
        default:
            break;
    }
    if(height > _maxRadian){
        NSLog(@"圓弧半徑過大, 跳過設(shè)置。");
        return;
    }
    
    // 計(jì)算半徑
    CGFloat radius = 0;
    switch (self.direction) {
        case DXRadianDirectionBottom:
        case DXRadianDirectionTop:
        {
            CGFloat c = sqrt(pow(t_width / 2, 2) + pow(height, 2));
            CGFloat sin_bc = height / c;
            radius = c / ( sin_bc * 2);
        }
            break;
        case DXRadianDirectionLeft:
        case DXRadianDirectionRight:
        {
            CGFloat c = sqrt(pow(t_height / 2, 2) + pow(height, 2));
            CGFloat sin_bc = height / c;
            radius = c / ( sin_bc * 2);
        }
            break;
        default:
            break;
    }
    
    // 畫圓
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    [shapeLayer setFillColor:[[UIColor whiteColor] CGColor]];
    CGMutablePathRef path = CGPathCreateMutable();
    switch (self.direction) {
        case DXRadianDirectionBottom:
        {
            if(radian > 0){
                CGPathMoveToPoint(path,NULL, t_width,t_height - height);
                CGPathAddArc(path,NULL, t_width / 2, t_height - radius, radius, asin((radius - height ) / radius), M_PI - asin((radius - height ) / radius), NO);
            }else{
                CGPathMoveToPoint(path,NULL, t_width,t_height);
                CGPathAddArc(path,NULL, t_width / 2, t_height + radius - height, radius, 2 * M_PI - asin((radius - height ) / radius), M_PI + asin((radius - height ) / radius), YES);
            }
            CGPathAddLineToPoint(path,NULL, x, y);
            CGPathAddLineToPoint(path,NULL, t_width, y);
        }
            break;
        case DXRadianDirectionTop:
        {
            if(radian > 0){
                CGPathMoveToPoint(path,NULL, t_width, height);
                CGPathAddArc(path,NULL, t_width / 2, radius, radius, 2 * M_PI - asin((radius - height ) / radius), M_PI + asin((radius - height ) / radius), YES);
            }else{
                CGPathMoveToPoint(path,NULL, t_width, y);
                CGPathAddArc(path,NULL, t_width / 2, height - radius, radius, asin((radius - height ) / radius), M_PI - asin((radius - height ) / radius), NO);
            }
            CGPathAddLineToPoint(path,NULL, x, t_height);
            CGPathAddLineToPoint(path,NULL, t_width, t_height);
        }
            break;
        case DXRadianDirectionLeft:
        {
            if(radian > 0){
                CGPathMoveToPoint(path,NULL, height, y);
                CGPathAddArc(path,NULL, radius, t_height / 2, radius, M_PI + asin((radius - height ) / radius), M_PI - asin((radius - height ) / radius), YES);
            }else{
                CGPathMoveToPoint(path,NULL, x, y);
                CGPathAddArc(path,NULL, height - radius, t_height / 2, radius, 2 * M_PI - asin((radius - height ) / radius), asin((radius - height ) / radius), NO);
            }
            CGPathAddLineToPoint(path,NULL, t_width, t_height);
            CGPathAddLineToPoint(path,NULL, t_width, y);
        }
            break;
        case DXRadianDirectionRight:
        {
            if(radian > 0){
                CGPathMoveToPoint(path,NULL, t_width - height, y);
                CGPathAddArc(path,NULL, t_width - radius, t_height / 2, radius, 1.5 * M_PI + asin((radius - height ) / radius), M_PI / 2 + asin((radius - height ) / radius), NO);
            }else{
                CGPathMoveToPoint(path,NULL, t_width, y);
                CGPathAddArc(path,NULL, t_width  + radius - height, t_height / 2, radius, M_PI + asin((radius - height ) / radius), M_PI - asin((radius - height ) / radius), YES);
            }
            CGPathAddLineToPoint(path,NULL, x, t_height);
            CGPathAddLineToPoint(path,NULL, x, y);
        }
            break;
        default:
            break;
    }
    
    CGPathCloseSubpath(path);
    [shapeLayer setPath:path];
    CFRelease(path);
    self.layer.mask = shapeLayer;
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容