1,开始的思路

公司想做直播方面的项目,并想加入弹幕的功能,直播的页面已经作为一个组件放在了用react+redux写好的一个网站项目上。
所以技术老大让我研究下如何用react实现弹幕的功能。下面我就简单说下我的react弹幕折腾之路。
一开始其实是两手空空,作为一个php的初级开发人员,我对前端技术掌握的很少,远不到熟练的程度。所以,我得从头学习如何用js+css实现弹幕,然后再将弹幕移植到react项目上去,这是我一开始的思路。

2,中间的折腾

我百度了下“js 弹幕”,发现大部分都是用jquery的animate()函数和css配合来实现的,比如这个HTML+CSS+jQuery实现弹幕技术,有些则是jquery配合css的animation来实现。
我学习了下用jquery的animate()函数配合css来实现弹幕的方法,然后就尝试将这个方法引入到react项目中去。但我在这个地方费了好多时间都没有进展,最终我放弃了将jquery引入react的想法。技术老大提醒我,可以找找react动画的解决方法。
于是百度、google,在sgemenfault和知乎上有不少问答,给出了三个解决方向:
1,用react官方提供的动画插件(ReactCSSTransitionGroup)可以实现基本和简单的动画
2,引入专业的第三方的动画库
3,用第三方的react动画插件
第1种方法,简单、直接,需要对react的动画插件有所了解,第2种方法需要非常熟悉第三方库的用法,像我这种前端的半吊子还是算了:),第3种方法,我也没考虑。
总之,我选择了第1种。我大致看了下react官方的tutorial和docs,然后就开始动手了。

3,初现曙光

按照react官网上给的TodoList例子,我写出了我的第1个react动画(没有用到redux),

实现的基本功能就是在一个输入框中输入文字,然后enter发送文字,文字从一个div的右侧走到左侧,最后消失。先把代码贴出来:

点击我查看代码

 import React from 'react';
 import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

 class App extends React.Component {
   constructor(props) {
     super(props);
     this.state = {
       word: '',
       value: '',
       index: 0,
       top: 0,
     };
     this.returnWord = this.returnWord.bind(this);
     this.handleChange = this.handleChange.bind(this);
     this.handleSubmit = this.handleSubmit.bind(this);
   }

   componentDidMount() {
     // 监听回车事件
     document.onkeydown = (event) => {
       if (event.keyCode === 13) {
         document.getElementById('sendBullet').click = null;
       }
     };
   }

   handleSubmit(event) {
     event.preventDefault();
     this.setState({ value: '' });
   }

   handleChange(event) {
     this.setState({ value: event.target.value });
   }

   returnWord() {
     const word = this.myTextInput;
     const index = this.state.index;
     const top = this.state.top;
     if (word === this.state.value) {
       this.setState({ word, index: index + 1 });
     }
     if (top <= 435) {
       this.setState({ top: top + 75 });
     } else if (top > 435) {
       this.setState({ top: 0 });
     }
   }

   render() {
     const item = (
       <div
         className="bullet"
         key={this.state.index}
         style={{ top: `${this.state.top}px`, color: `#${((1 << 24) * Math.random() | 0).toString(16)}` }}
       >
         {this.state.word}
       </div>
     );

     return (
       <div>
         <form onSubmit={this.handleSubmit}>
           <input
             type="text"
             ref={
               (ref) => {
                 if (ref !== null && ref.value.trim() !== '') {
                   this.myTextInput = ref.value;
                 }
               }
             }
             value={this.state.value}
             onChange={this.handleChange}
           />
         <button id="sendBullet" onClick={this.returnWord}>发送弹幕</button>
           <div
             style={{
               position: 'relative',
               width: '1200px',
               height: '500px',
               margin: 'auto',
               background: 'rgba(255, 0, 0, 0.1)',
               overflow: 'hidden',
             }}
           >
             <ReactCSSTransitionGroup
               transitionName={{
                 enter: 'bullet-enter',
               }}
               transitionEnterTimeout={5000}
               transitionLeave={false}
             >
               {item}
             </ReactCSSTransitionGroup>
           </div>
         </form>
       </div>
     );
   }
 }

 export default App;

可以看到我这里引入了ReactCSSTransitionGroup它是react提供的一个动画插件,可以实现基本、简单的css动画和渐变功能,它需要单独安装,具体的安装方法可以百度或google。

下面来说下比较关键的地方:

1,代码第51~59行,定义要动的弹幕文字组件。 render方法中定义了一个item,这个item就是弹幕中要动起来的弹幕文字组件。要注意:item中的key属性是必须要给定的,哪怕你只有单独的1个item也要指定key,

这样React才能决定哪个item该如何动作,这也是react官方文档中所强调的。我定义了自增的index作为state来管理item的key,这样每个item都有一个唯一的key。

2,代码第87~95行,ReactCSSTransitionGroup配置。需要注意的是,一定要将要操纵的动画元素完全包含到ReactCSSTransitionGroup中去,然后就是根据动画需要设置要做的动画过程。我只要入场动画(有字幕出现时就开始动画)就可以了。

所以设置入场动画时间transitionEnterTimeout={5000}。另外,出场动画不需要可以设置为false: transitionLeave={false},不能忽略这个属性,不然会报错。transitionName中可以设置动画过程的css样式名称,设置规则可参考官网。

3,下面是我的入场动画css样式,也是要注意的第3点

 .bullet {
   opacity: 0.01;
 }

 .bullet-enter {
 ;
   position: absolute;
   left: 1100px;
 }

 .bullet-enter.bullet-enter-active {
   opacity: .5;
   position: absolute;
   left: -100px;
   transition: all 5000ms ease-in;
 }

.bullet-enter对应入场动画开始时的item样式,.bullet-enter.bullet-enter-active对应入场动画结束时的item样式,可以看到用到了css的transition,这也是实现动画的关键。

以上3点比较关键,其余的问题就是如何产生item的问题,这个暂时先不写了。

4,将弹幕作为一个组件整合到react+redux项目中

其实只要实现了弹幕动画,整合也就容易了,下面先把弹幕组件的代码贴出来。

 import React, { Component, PropTypes } from 'react';
 import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

 class BulletScreen extends Component {

   render() {
     const item = (
       <div
         className="bullet"
         key={this.props.index}
         style={{
           top: `${this.props.top}vh`,
           color: 'rgb(255, 255, 255)',
           whiteSpace: 'nowrap',
           fontSize: '3vh',
         }}
       >
         {this.props.word}
       </div>
     );

     return (
       <div
         id="bullt-screen"
         style={{
           position: 'relative',
           width: 'auto',
           height: '46vh',
           overflow: 'hidden',
           margin: '-50vh auto auto auto',
           background: 'rgba(0, 255, 0, 0.01)',
         }}
       >
         <ReactCSSTransitionGroup
           transitionName={{
             enter: 'bullet-enter',
           }}
           transitionEnterTimeout={5000}
           transitionLeave={false}
         >
           {item}
         </ReactCSSTransitionGroup>
       </div>
     );
   }
 }

 BulletScreen.propTypes = {
   word: PropTypes.string,
   index: PropTypes.number,
   top: PropTypes.number,
 };

 export default BulletScreen;

到时在视频播放的页面中引入这个组件就可以了。

这个项目目前是我司的开源项目,感兴趣的朋友可以去github上看下: wecan-tv-frontend

参考资料:
HTML+CSS+jQuery实现弹幕技术
Animation Add-Ons

用react的ReactCSSTransitionGroup插件实现简单的弹幕动画的更多相关文章

  1. Xcode7使用插件的简单方法&amp;&amp;以及怎样下载到更早版本的Xcode

    Xcode7自2015年9上架以来也有段时间了, 使用Xcode7以及Xcode7.1\Xcode7.2的小伙伴会发现像VVDocumenter-Xcode\KSImageNamed-Xcode\HO ...

  2. 移动端全屏滑动的小插件,简单,轻便,好用,只有3k swiper,myswiper,page,stage

    https://github.com/donglegend/mySwiper mySwiper 移动端全屏滑动的小插件,简单,轻便,好用,只有3k 下载 直接下载 bower install mySw ...

  3. 数据统计表插件,highcharts插件的简单应用

    highcharts插件的简单应用,非常全能好用的一个数据统计表插件. $(function () { $('#container').highcharts({ chart:{ type:" ...

  4. ASP.NET MVC5 插件机制中插件的简单实现

    Autofac 依赖注入 ASP.NET MVC5 插件机制中插件的简单实现 一.前言 由于项目业务复杂,创建了多个插件并把他们放在了不同的项目中,项目使用AutoFac做的IOC:但是主项目可以注入 ...

  5. Atom编辑器之加快React开发的插件汇总

    汇总下比较实用的atom插件[偏react开发的]-- 博主发现这个还是比较全面的! atom-react-autocomplete–项目内,组件名及状态的自动补全  autocomplete-js- ...

  6. swiper插件的简单使用,实现图片轮播

    移动端和p c端经常会遇到写轮播图的情况,这里只是简单的说一下swiper插件的简单用法(移动端为例). <!DOCTYPE html> <html lang="en&qu ...

  7. 基于jquery fly插件实现加入购物车抛物线动画效果,jquery.fly.js

    在购物网站中,加入购物车的功能是必须的功能,有的网站在用户点击加入购物车按钮时,就会出现该商品从点击出以抛物线的动画相似加入购物车,这个功能看起来非常炫,对用户体验也有一定的提高.下面介绍基于jque ...

  8. Android简单逐帧动画Frame的实现(二)

    Android简单逐帧动画Frame的实现   Android简单逐帧动画Frame的实现 1.逐帧动画 即是通过播放预先排序好的图片来实现动态的画面,感觉像是放电影. 2.实现步骤: 1. 在工程里 ...

  9. 【UI插件】简单的日历插件(下)—— 学习MVC思想

    前言 我们上次写了一个简单的日历插件,但是只是一个半成品,而且做完后发现一些问题,于是我们今天尝试来解决这些问题 PS:距离上次貌似很久了 上次,我们大概遇到哪些问题呢: ① 既然想做一套UI库,那么 ...

随机推荐

  1. STM32用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain现象和解决方案

    现象 CPU: STM32107VC 用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain 如图无法查找到硬件就是CPU 提示1:NO Cortex ...

  2. PowerShell脚本自动设置安卓手机wifi代理

    在实际测试工作中,经常要将安卓手机通过wifi代理的形式连接到本机的fiddler或charles服务器代理进行抓包测试.最近一直在想,有没有什么方法可以自动设置安卓手机的wifi代理,曾经想通过修改 ...

  3. 使用FIR.im发布自己的移动端APP

    一次很偶然的机会知道FIR.im,这家公司主要的产品就是帮助开发者方便便捷地发布iOS或者Android应用的.今天我就聊聊如何在FIR.im中发布自己的APP,然后让加入UUID的设备通过网页直接下 ...

  4. 我们的动机(Our motivation)

    我们的动机(Our motivation) There are many PHP frameworks nowadays, but none of them is like Phalcon (Real ...

  5. Linq to json

    Json.Net系列教程 4.Linq To JSON 一.Linq to JSON是用来干什么的? Linq to JSON是用来操作JSON对象的.可以用于快速查询,修改和创建JSON对象.当JS ...

  6. 2016HUAS_ACM暑假集训2L - Points on Cycle(圆上的点)

    一个简单的几何题,自己在纸上列出方程解出结果的表达式,再用程序表达出来就行了. 不过老司机(老司机的woodcoding)说用旋转向量法比较简单,有时间要去看一看. 大致题意:一个圆心在原点的圆,半径 ...

  7. Xaml/Xml 实现对象与存储分离

    刚开始用xml存储东西的时候都是不断的在xml文件里面添加或者修改xml的节点,这个是很常见的做法,这方面的博客也很多我也就不介绍了.但其实在小批量存储的时候我们可以直接将对象存进xml/xaml,使 ...

  8. HDU 5003 Osu!

    解题思路:水题,不多说. #include<cstdio> #include<cstring> #include<algorithm> #include<cm ...

  9. c++,windows中的字符问题

    string与char*的转换方法 string a; char *b=a.c_str(); string a=new String(b); a=b; LPCWSTR是unicode的字符串,LPCS ...

  10. 人体时钟hone hone clock

    摘要:一个由日本人设计的有意思的Flash时钟:人体时钟 hone hone clock .安装很简单,直接js导入即可,包括两种样式:透明背景和白色背景. 很可爱的一个设计,实现后效果如下: 使用方 ...