十六 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值