add flying commit

This commit is contained in:
lianxiang
2018-08-28 17:00:43 +08:00
parent 6a8d55457a
commit 54e936535f
24 changed files with 1353 additions and 23 deletions
@@ -0,0 +1,34 @@
//
// LXDanMuManager.h
// LXAnimationTest
//
// Created by lianxiang on 2018/8/14.
// Copyright © 2018年 com.giga.ios. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface LXDanMuManager : NSObject
@property (nonatomic,strong) NSArray *trackSpeedArray;
@property (nonatomic,assign) float centerY;//所有轨道中心点
@property (nonatomic,assign) float trackWidth;
@property (nonatomic,strong) NSTimer *timer;
@property (nonatomic,strong) UIView *superView;
@property (nonatomic,strong) NSMutableArray *trackArray;
@property (nonatomic,strong) UIView *baseView;
+(LXDanMuManager *)shareInstance;
-(void)createDanmuWithTrackSpeedArray:(NSArray *)trackSpeedArray centerY:(float)centerY trackWidth:(float)trackWidth showInView:(UIView *)inView;
/**
插入一条弹幕,可以插入任意继承UIView的对象
@param customView 自定义的view(注意,最高不能超过轨道的高,否则会出问题)
@param trackIndex 插入弹幕的轨道(为-1则代表自动寻找最不拥挤的轨道插入)
*/
-(void)appendDanMuWithCustomView:(UIView *)customView toTrackIndex:(NSInteger)trackIndex;
-(void)start;
-(void)pause;
-(void)stop;
-(void)destory;
@end
+145
View File
@@ -0,0 +1,145 @@
//
// LXDanMuManager.m
// LXAnimationTest
//
// Created by lianxiang on 2018/8/14.
// Copyright © 2018年 com.giga.ios. All rights reserved.
//
#import "LXDanMuManager.h"
#import "LXDanMuTrackView.h"
@implementation LXDanMuManager
+ (LXDanMuManager *)shareInstance{
static LXDanMuManager *managerInstance = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
managerInstance = [[self alloc] init];
});
return managerInstance;
}
- (void)createDanmuWithTrackSpeedArray:(NSArray *)trackSpeedArray centerY:(float)centerY trackWidth:(float)trackWidth showInView:(UIView *)inView{
_superView = inView;
_trackSpeedArray = trackSpeedArray;
_centerY = centerY;
_trackWidth = trackWidth;
_trackArray = [[NSMutableArray alloc] init];
[self initUI];
}
-(void)initUI{
_baseView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,_trackWidth, 0)];
_baseView.userInteractionEnabled = NO;
[_superView addSubview:_baseView];
for (int i = 0; i<_trackSpeedArray.count; i++) {
LXDanMuTrackView *trackView = [[LXDanMuTrackView alloc] initWithFrame:CGRectMake(0, (TRACK_HEIGHT + TRACK_VERTICAL_PADDING) * i, _baseView.frame.size.width, TRACK_HEIGHT)];
[_baseView addSubview:trackView];
[_trackArray addObject:trackView];
if (_trackSpeedArray.count - 1 == i) {
_baseView.frame = CGRectMake(_baseView.frame.origin.x, _baseView.frame.origin.y, _baseView.frame.size.width,CGRectGetMaxY(trackView.frame));
_baseView.center = CGPointMake(_baseView.center.x, _centerY);
}
}
}
-(void)start{
if (_timer) {
return;
}
_timer = [NSTimer timerWithTimeInterval:0.01 target:self selector:@selector(startAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
- (void)pause{
[_timer invalidate];
_timer = nil;
}
- (void)stop{
[_timer invalidate];
_timer = nil;
for (LXDanMuTrackView *trackView in _trackArray) {
[trackView cleanTrack];
}
}
- (void)destory{
[_timer invalidate];
_timer = nil;
for (LXDanMuTrackView * trackView in _trackArray) {
[trackView cleanTrack];
[trackView removeFromSuperview];
}
[_trackArray removeAllObjects];
[_baseView removeFromSuperview];
_trackSpeedArray = nil;
_superView = nil;
_baseView = nil;
_trackArray = nil;
}
-(void)startAction{
for (int i = 0; i < _trackArray.count; i++) {
//执行轨道定时器方法
LXDanMuTrackView *trackView = _trackArray[i];
[trackView moveViewWithSpeed:[_trackSpeedArray[i] floatValue]];
}
}
-(UIView *)baseView{
if (!_baseView) {
_baseView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,_trackWidth, 0)];
}
return _baseView;
}
//自定义的view(注意,最高不能超过轨道的高,会出问题)
- (void)appendDanMuWithCustomView:(UIView *)customView toTrackIndex:(NSInteger)trackIndex
{
//trackIndex 插入弹幕的轨道(为-1则代表自动寻找最不拥挤的轨道插入)
NSInteger realTrackIndex = trackIndex;
if (realTrackIndex == -1) {
realTrackIndex = [self findTheMinTotalWidthTrack];
}
LXDanMuTrackView *trackView = _trackArray[realTrackIndex];
[trackView appendWithCustomView:customView];
}
/**
找到最短右侧出屏幕和等待数组总长度最短的轨道序号
@return 轨道的序号
*/
- (int)findTheMinTotalWidthTrack
{
LXDanMuTrackView *firstTrackView = _trackArray[0];
int minWidthIndex = 0;
float minWidth = [firstTrackView rightOutScreenWidth];
for (int i = 0; i<_trackArray.count; i++)
{
LXDanMuTrackView *trackView = _trackArray[i];
float trackRightOutScreenWidth = [trackView rightOutScreenWidth];
if (trackRightOutScreenWidth < minWidth)
{
minWidth = trackRightOutScreenWidth;
minWidthIndex = i;
}
}
return minWidthIndex;
}
@end
@@ -0,0 +1,19 @@
//
// LXDanMuManagerConfig.h
// LXAnimationTest
//
// Created by lianxiang on 2018/8/14.
// Copyright © 2018年 com.giga.ios. All rights reserved.
//
#ifndef LXDanMuManagerConfig_h
#define LXDanMuManagerConfig_h
//轨道中弹幕的最小间距
#define TRACK_HORIZONTAL_PADDING 10
//轨道与轨道的纵向间距
#define TRACK_VERTICAL_PADDING 10
//轨道的高度(轨道上的View不能超过此高度)
#define TRACK_HEIGHT 60
#endif /* LXDanMuManagerConfig_h */
@@ -0,0 +1,47 @@
//
// LXDanMuTrackView.h
// LXAnimationTest
//
// Created by lianxiang on 2018/8/14.
// Copyright © 2018年 com.giga.ios. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "LXDanMuManagerConfig.h"
@interface LXDanMuTrackView : UIView
/**
等待出现到屏幕中的弹幕view数组
*/
@property (nonatomic,strong) NSMutableArray *waitShowArray;
/**
正在展示的弹幕view数组
*/
@property (nonatomic,strong) NSMutableArray *showingArray;
/**
向轨道中插入一条自定义的view
@param view 自定义的view,高度不可超过轨道的高,否则出问题
*/
- (void)appendWithCustomView:(UIView *)view;
/**
当前轨道右侧出屏幕的距离+等待出现到屏幕中的弹幕view的总长度和
@return 等待弹幕+右侧出屏幕弹幕的和
*/
- (float)rightOutScreenWidth;
/**
清理轨道,移除所有弹幕
*/
- (void)cleanTrack;
/**
根据速度移动轨道中所有弹幕的位置
@param speed 每0.01秒弹幕向左移动的距离
*/
- (void)moveViewWithSpeed:(float)speed;
@end
@@ -0,0 +1,123 @@
//
// LXDanMuTrackView.m
// LXAnimationTest
//
// Created by lianxiang on 2018/8/14.
// Copyright © 2018年 com.giga.ios. All rights reserved.
//
#import "LXDanMuTrackView.h"
@implementation LXDanMuTrackView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self dataConfig];
}
return self;
}
-(void)dataConfig{
_showingArray = [[NSMutableArray alloc] init];
_waitShowArray = [[NSMutableArray alloc] init];
}
- (void)appendWithCustomView:(UIView *)view{
view.frame = CGRectMake(self.frame.size.width,view.frame.origin.y, view.frame.size.width,view.frame.size.height);
view.center = CGPointMake(view.center.x, TRACK_HEIGHT/2);
if (_showingArray.count) {
UIView *lastView = [_showingArray lastObject];
//最右侧的那条弹幕还没有完全出现在屏幕中
if (CGRectGetMaxX(lastView.frame) + TRACK_HORIZONTAL_PADDING > self.frame.size.width || _waitShowArray.count) {
//把这条弹幕加到等待数组中
[_waitShowArray addObject:view];
}else{
//加入轨道
[self addSubview:view];
//加入展示数组
[_showingArray addObject:view];
}
}else{
[self addSubview:view];
[_showingArray addObject:view];
}
}
- (void)moveViewWithSpeed:(float)speed{
//正在展示的弹幕自减一次
for (UIView *view in _showingArray) {
view.frame = CGRectMake(view.frame.origin.x - speed, view.frame.origin.y, view.frame.size.width, view.frame.size.height);
}
//正在展示的弹幕
if (_showingArray.count){
UIView *firstView = [_showingArray firstObject];
UIView *lastView = [_showingArray lastObject];
if (CGRectGetMaxX(firstView.frame) < 0) {
//已移除屏幕 remove
[firstView removeFromSuperview];
[_showingArray removeObjectAtIndex:0];
}
if (_waitShowArray.count) {
//最右侧的view 已经完全出现
if (CGRectGetMaxX(lastView.frame) + TRACK_HORIZONTAL_PADDING <= self.frame.size.width) {
//转移数组
[_showingArray addObject:[_waitShowArray firstObject]];
[_waitShowArray removeObjectAtIndex:0];
[self addSubview:[_showingArray lastObject]];
}
}
}
}
- (float)rightOutScreenWidth
{
float outScreenWidth = 0.0;
//如果等待数组中有值
if (_waitShowArray.count)
{
//先遍历所有等待数组中的view,累加长度和间距
for (UIView *view in _waitShowArray)
{
outScreenWidth += view.frame.size.width + TRACK_HORIZONTAL_PADDING;
}
}
//如果展示数组中有值
if (_showingArray.count)
{
//拿出最右侧的view
UIView *lastView = [_showingArray lastObject];
//算出出屏宽
float rightOutWidth = CGRectGetMaxX(lastView.frame) - self.frame.size.width;
if (rightOutWidth < 0)
{
rightOutWidth = 0;
}
outScreenWidth += rightOutWidth;
}
return outScreenWidth;
}
//清理轨道
- (void)cleanTrack
{
for (UIView *view in _showingArray)
{
[view removeFromSuperview];
}
[_showingArray removeAllObjects];
[_waitShowArray removeAllObjects];
}
@end