十六 iOS之 酷炫彈幕(二)

這次基於上一次的demo做更復雜點的功能,原理是 通過加載我自己準備的plist文件裏的數據,生成一張張圖文混排的圖片,讓它們從屏幕上飄過,就達到了彈幕效果


效果圖:每次點擊屏幕就飄出一條彈幕

這裏寫圖片描述

一 主要添加了一個plist文件,和一個模型類 DGDanMuModel

  • DGDanMuModel.h
#import <UIKit/UIKit.h>

//彈幕類型枚舉, 0就是其他人,1就是自己
typedef enum {
    DGDanMuTypeOther,
    DGDanMuTypeMe,
} DGDanMuType;

@interface DGDanMuModel : NSObject


/**彈幕類型*/
@property(nonatomic,assign)DGDanMuType type;
/**用戶名*/
@property(nonatomic,copy)NSString * username;
/**文本內容*/
@property(nonatomic,copy)NSString * text;
/**頭像*/
@property(nonatomic,strong)UIImage * icon;
/**表情圖片名數組*/
@property(nonatomic,strong)NSArray<NSString*> * emotions;
/**
 字典轉模型方法
*/
+(instancetype)danMuWithDict:(NSDictionary*)dict;

@end
  • DGDanMuModel.m
#import "DGDanMuModel.h"

@implementation DGDanMuModel

/**
 字典轉模型方法

 @param dict 要轉的字典
 @return 模型對象
 */
+(instancetype)danMuWithDict:(NSDictionary*)dict
{
    id obj = [[self alloc]init];

    [obj setValuesForKeysWithDictionary:dict];

    return obj;
}

@end

二 在DGDanMuView中增加了一個繪製彈幕的方法

如下圖,分成四部分去繪製這個圖:頭像、名稱、文本、表情,相應部分的位置大小都參照這個圖去計算
這裏寫圖片描述

  • 這個方法的核心代碼
/**
 根據彈幕模型生成彈幕圖片
 */
-(DGImage*)imageWithDanMu:(DGDanMuModel*)danMu
{
    //繪製文字使用的字體
    UIFont * font = [UIFont systemFontOfSize:13];

    //間距
    CGFloat marginX = 5;
    //頭像的尺寸
    CGFloat iconH = 30;
    CGFloat iconW = iconH;

    //表情圖片的尺寸
    CGFloat emotioW = 25;
    CGFloat emotionH = emotioW;

    //計算用戶名佔據的實際區域
    CGSize nameSize =  [danMu.username boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil].size;

    //用戶名字體高度
    CGFloat nameFontH = nameSize.height;


    //計算內容佔據的實際區域
    CGSize textSize =  [danMu.text boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil].size;

    //內容字體高度
    CGFloat textFontH = textSize.height;


    //位圖上下文的尺寸
    CGFloat contextH = iconH;
    //位圖上下文的寬度 = 頭像的寬度 + 1個間距 + 1個間距 + 用戶名的寬度 + 1個間距 + 內容的寬度 + 表情的寬度 * 個數 + 1個間距
    CGFloat contextW = iconW + marginX * 2 + nameSize.width + marginX + textSize.width + marginX + danMu.emotions.count * emotioW;


    CGSize contextSize = CGSizeMake(contextW, contextH);

    //開啓位圖上下文
    UIGraphicsBeginImageContextWithOptions(contextSize, NO, 0);

    //獲得位圖上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    //將上下文保存一份到棧中,因爲繪製頭像時會裁剪點一部分上下文
    CGContextSaveGState(ctx);

    //--------------繪製頭像-------------//
    //設置頭像尺寸
    CGRect iconFrame = CGRectMake(0, 0, iconW, iconH);
    //繪製頭像圓形
    CGContextAddEllipseInRect(ctx, iconFrame);
    //超出圓形範圍內的內容裁減掉
    CGContextClip(ctx);

    UIImage * icon = danMu.type ? [UIImage imageNamed:@"me"] : [UIImage imageNamed:@"other"];
    //繪製頭像
    [icon drawInRect:iconFrame];

    //------------- 繪製背景圖片----------------//
    //將上下文出棧
    CGContextRestoreGState(ctx);
    //繪製背景圖片
    CGFloat bgX = iconW + marginX;
    CGFloat bgY = 0;
    CGFloat bgW = contextW - bgX;
    CGFloat bgH = contextH;

    danMu.type ? [[UIColor orangeColor] set] : [[UIColor whiteColor] set];

    [[UIBezierPath bezierPathWithRoundedRect:CGRectMake(bgX, bgY, bgW, bgH) cornerRadius:20] fill];

    //-----------------繪製用戶名---------------//
    CGFloat nameX = bgX + marginX;
    CGFloat nameY = (contextH - nameFontH) * 0.5;
    CGRect nameRect = CGRectMake(nameX, nameY, nameSize.width, nameSize.height);
    [danMu.username drawInRect:nameRect withAttributes:@{NSFontAttributeName:font,NSForegroundColorAttributeName : danMu.type ? [UIColor blackColor] : [UIColor orangeColor]}];

    //----------------繪製文本區域 --------------------//
    CGFloat textX = nameX + nameSize.width + marginX;
    CGFloat textY = (contextH - textFontH) * 0.5;
    CGRect textRect = CGRectMake(textX, textY, textSize.width, textSize.height);

    [danMu.text drawInRect:textRect withAttributes:@{NSFontAttributeName:font,NSForegroundColorAttributeName : danMu.type ? [UIColor whiteColor] : [UIColor blackColor]}];

    //----------------繪製表情圖片 --------------------//
   __block CGFloat emotionX = textX + textSize.width;
    CGFloat emotionY = (contextH - emotionH) * 0.5;

    [danMu.emotions enumerateObjectsUsingBlock:^(NSString * _Nonnull emotionName, NSUInteger idx, BOOL * _Nonnull stop) {

        //加載表情圖片
        UIImage * emotion = [UIImage imageNamed:emotionName];

        [emotion drawInRect:CGRectMake(emotionX, emotionY, emotioW, emotionH)];

        emotionX += emotioW;


    }];

    //從位圖上下文獲得繪製好的圖片
    UIImage * image = UIGraphicsGetImageFromCurrentImageContext();

    //根據屏幕比例返回這張圖片
    return [[DGImage alloc]initWithCGImage:image.CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
}

github demo: BarragePerfectDemo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章