這次基於上一次的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];
}