preface
This year, due to the epidemic, schools have been closed for a long time. Online education was already very popular, but now it is even more explosive. There are so many online education apps, and the growth is even more amazing.
Adult education video is still the conventional video, there is no big change, but the main video teaching of the young children market, in order to let the children interested, it is to play a lot of tricks, such as zebra AI class, small spark thinking and other main video interactive class, such as Hongen literacy is a game.
The video interaction course directly overturns my perception of video interaction. Before seeing it, all I had ever known about video interaction was Posting a bullet screen or clicking a thumbs-up on the video. Video interactive class in our developer’s view, is to jump out of the video for some operations, complete in the video back. It seems to ordinary people or children that I am interacting with the characters in the video. The general routine is to play an animation, the characters in the animation need to do something, the children need to help, the children need to complete some small games, in the small game to learn the knowledge, or play a piece of music, let the children sing and dance. The product design is really amazing. Kids are really stickiness, parents are happy, finally can stop, but also can learn. Watch one video class a day, plus after-school practice games and other interactions for 20 minutes to half an hour. The damage to children’s eyes is not great. Let me watch the recording of the video interactive class
First of all, there are 4 time ICONS on the progress bar under the video, representing these 4 events. The location of the time point is known at or before the beginning of the video. The time point of each class is different, so we designed the icon on the progress bar to determine the position according to the data of the time point.
Next imitate video interactive class, try to achieve
ZFPlayer is used to create the node data model
@interface ZBGameModel : NSObject @property (nonatomic,assign)NSInteger seconds; @property (nonatomic,assign)NSInteger gameId; // game id @property (nonatomic,assign)NSInteger gameType; // Game type 1 is game @endCopy the code
Assign the model the corresponding time and type
ZBGameModel *model1=[[ZBGameModel alloc]init];
model1.gameId=1001;
model1.gameType=1;
model1.seconds=100;
ZBGameModel *model2=[[ZBGameModel alloc]init];
model2.gameId=1002;
model2.gameType=1;
model2.seconds=221;
ZBGameModel *model3=[[ZBGameModel alloc]init];
model3.gameId=1003;
model3.gameType=1;
model3.seconds=303;
ZBGameModel *model4=[[ZBGameModel alloc]init];
model4.gameId=1004;
model4.gameType=2;
model4.seconds=318;
[self.timeArray addObject:model1];
[self.timeArray addObject:model2];
[self.timeArray addObject:model3];
[self.timeArray addObject:model4];
Copy the code
According to the picture above, we can see that the tick mark represents the game, and the last music mark represents the nursery rhyme time. But this icon, how do we calculate the position coordinates.
The next step is to calculate (the total length of the progress bar/the total time of the video) * the corresponding point in time – half of the width of the icon to get the position of each icon
/ / / when players ready to play calls self. Player. PlayerReadyToPlay = ^ (id < ZFPlayerMediaPlayback > _Nonnull asset, NSURL * _Nonnull assetURL) { @strongify(self) [self.timeArray enumerateObjectsUsingBlock:^(ZBGameModel *model, NSUInteger idx, BOOL * _Nonnull stop) { UIImageView *icon=[[UIImageView alloc]init]; if (model.gameType==1) { icon.image=[UIImage imageNamed:@"gift_icon_0"]; }else{ icon.image=[UIImage imageNamed:@"douyin"]; } icon.backgroundColor=[UIColor whiteColor]; [self.controlView.landScapeControlView.slider addSubview:icon]; [icon mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(@(0)); make.width.equalTo(@(14)); Make.height.equalto (@(14)); //7 is half the width make.left.equalTo(@(model.seconds*(self.controlView.landScapeControlView.slider.frame.size.width/self.playerManager.tota lTime)-7)); }]; }]; };Copy the code
Because it’s just a demo, I didn’t customize the video control layer just like in the interactive video class, but you can see that the ICONS are pretty much the same as the original ICONS are the UI level, so how do we get into the game when it’s time for the game ICONS to create a game queue class and pass in the data that we just did
self.gameQueue=[[ZBGameQueue alloc]init]; self.gameQueue.delegate=self; [self. GameQueue loadGameList: self timeArray];Copy the code
So it’s going to look like this, and it’s going to store the model data in the dictionary, with the node time as the key
- (void)loadGameList:(NSArray *)gameList{ if (gameList.count<=0) { return; } for (int i = 0; i < gameList.count; i ++) { ZBGameModel *gameModel = gameList[i]; [self.cacheDict setObject:gameModel forKey:@(gameModel.seconds).stringValue]; }}Copy the code
Match the game time and video time in the video time callback, find the corresponding time point, prove that you can enter the game
__block NSInteger tempTime; self.player.playerPlayTimeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSTimeInterval currentTime, @strongify(self) {tempTime=currentTime; if (self.currentTime! =tempTime) { NSLog(@"tempTime:%ld",tempTime); / / lined up and video game time contrast [self. GameQueue startQueueWithCurrentTime: tempTime]; } self.currentTime=tempTime; };Copy the code
- (void)startQueueWithCurrentTime:(NSInteger)currentTime{ if ([self.cacheDict.allKeys containsObject:@(currentTime).stringValue]) { ZBGameModel *gameModel =[self.cacheDict objectForKey:@(currentTime).stringValue]; if ([self.delegate respondsToSelector:@selector(gameQueueGetGameModel:)]) { [self.delegate gameQueueGetGameModel:gameModel]; }}}Copy the code
See this, if I have written before the history of bullet screen binding video time friends, should understand. The logic is the same. Then there’s the agent trigger, and we’re ready to play
#pragma mark - ZBGameQueueDelegate - (void)gameQueueGetGameModel:(ZBGameModel *)gameModel{ if (gameModel.gameType==1) { //1 for the game [self.playerManager pause]; // Pause the video NSLog(@" enter the game "); GameViewController *gameVC=[[GameViewController alloc]init]; gameVC.delegate=self; UIViewController *vc=[self.controlView.landScapeControlView findeCurrentViewController]; [vc presentViewController:gameVC animated:YES completion:nil]; }else{// other things do not jump like the children's song time}}Copy the code
The game part, I just wrote a little bit, three game nodes, all one. There are 3-4 games in one class video, and at least 10 games in practice after class. There are more than 10 classes for each age group, and the games are also different. With such a large number of games, it feels impossible to develop them native. Finally, a callback is given at the end of the game, and the video continues when the game ends
#pragma mark - GameViewControllerDelegate
- (void)gameComplete{
[self.playerManager play];
}
Copy the code
Through this process, our UI ICONS and events can be triggered accurately at any point in time and in any amount of data that the service sends or passes in
So let’s look at the overall effect
Finally, I present the Demo
End: the level is limited, the code is also very bad, has been studying hard, we forgive. If you like this wheel, please give a star, this is the biggest encouragement and support to the author, thank you!! If you have a better idea or plan, please leave a comment!