十六 iOS之 酷炫弹幕(二)

来源:互联网 发布:天龙八部天空视角数据 编辑:程序博客网 时间:2024/04/30 10:38

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

原创粉丝点击