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