用react的ReactCSSTransitionGroup插件实现简单的弹幕动画

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的右侧走到左侧,最后消失。先把代码贴出来:

点击我查看代码
  1 import React from 'react';
  2 import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
  3 
  4 class App extends React.Component {
  5   constructor(props) {
  6     super(props);
  7     this.state = {
  8       word: '',
  9       value: '',
 10       index: 0,
 11       top: 0,
 12     };
 13     this.returnWord = this.returnWord.bind(this);
 14     this.handleChange = this.handleChange.bind(this);
 15     this.handleSubmit = this.handleSubmit.bind(this);
 16   }
 17 
 18   componentDidMount() {
 19     // 监听回车事件
 20     document.onkeydown = (event) => {
 21       if (event.keyCode === 13) {
 22         document.getElementById('sendBullet').click = null;
 23       }
 24     };
 25   }
 26 
 27   handleSubmit(event) {
 28     event.preventDefault();
 29     this.setState({ value: '' });
 30   }
 31 
 32   handleChange(event) {
 33     this.setState({ value: event.target.value });
 34   }
 35 
 36   returnWord() {
 37     const word = this.myTextInput;
 38     const index = this.state.index;
 39     const top = this.state.top;
 40     if (word === this.state.value) {
 41       this.setState({ word, index: index + 1 });
 42     }
 43     if (top <= 435) {
 44       this.setState({ top: top + 75 });
 45     } else if (top > 435) {
 46       this.setState({ top: 0 });
 47     }
 48   }
 49 
 50   render() {
 51     const item = (
 52       <div
 53         className="bullet"
 54         key={this.state.index}
 55         style={{ top: `${this.state.top}px`, color: `#${((1 << 24) * Math.random() | 0).toString(16)}` }}
 56       >
 57         {this.state.word}
 58       
59 ); 60 61 return ( 62
63
this.handleSubmit}> 64 <input 65 type="text" 66 ref={ 67 (ref) => { 68 if (ref !== null && ref.value.trim() !== '') { 69 this.myTextInput = ref.value; 70 } 71 } 72 } 73 value={this.state.value} 74 onChange={this.handleChange} 75 /> 76 77 <div 78 style={{ 79 position: 'relative', 80 width: '1200px', 81 height: '500px', 82 margin: 'auto', 83 background: 'rgba(255, 0, 0, 0.1)', 84 overflow: 'hidden', 85 }} 86 > 87 <ReactCSSTransitionGroup 88 transitionName={{ 89 enter: 'bullet-enter', 90 }} 91 transitionEnterTimeout={5000} 92 transitionLeave={false} 93 > 94 {item} 95 96
97 98
99 ); 100 } 101 } 102 103 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点

 1 .bullet {
 2   opacity: 0.01;
 3 }
 4 
 5 .bullet-enter {
 6   opacity: 1;
 7   position: absolute;
 8   left: 1100px;
 9 }
10 
11 .bullet-enter.bullet-enter-active {
12   opacity: .5;
13   position: absolute;
14   left: -100px;
15   transition: all 5000ms ease-in;
16 }
View Code

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

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

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

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

 1 import React, { Component, PropTypes } from 'react';
 2 import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
 3 
 4 class BulletScreen extends Component {
 5 
 6   render() {
 7     const item = (
 8       <div
 9         className="bullet"
10         key={this.props.index}
11         style={{
12           top: `${this.props.top}vh`,
13           color: 'rgb(255, 255, 255)',
14           whiteSpace: 'nowrap',
15           fontSize: '3vh',
16         }}
17       >
18         {this.props.word}
19       
20 ); 21 22 return ( 23 <div 24 id="bullt-screen" 25 style={{ 26 position: 'relative', 27 width: 'auto', 28 height: '46vh', 29 overflow: 'hidden', 30 margin: '-50vh auto auto auto', 31 background: 'rgba(0, 255, 0, 0.01)', 32 }} 33 > 34 <ReactCSSTransitionGroup 35 transitionName={{ 36 enter: 'bullet-enter', 37 }} 38 transitionEnterTimeout={5000} 39 transitionLeave={false} 40 > 41 {item} 42 43
44 ); 45 } 46 } 47 48 BulletScreen.propTypes = { 49 word: PropTypes.string, 50 index: PropTypes.number, 51 top: PropTypes.number, 52 }; 53 54 export default BulletScreen;
View Code

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

 

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

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

转载于:https://www.cnblogs.com/yangtoude/p/5987958.html

你可能感兴趣的:(用react的ReactCSSTransitionGroup插件实现简单的弹幕动画)