rax 内置组件 rax-player 在 weex 环境的源码分析
一、描述
rax-player
是 rax 内置的视频播放组件,具有较多复杂的控制和功能,基本上能够满足在 weex 环境的视频播放需求。
而对于不同的容器环境,其处理的流程也不一样,在 weex 环境下还是直接依赖于 weex 的 video 组件。
整个 rax-player 组件在不同的容器中分为 video.weex.js
和 video.web.js
两个入口,源码中文件包含了 8 个 js 文件,不过在 weex 环境下则是最简单的。
二、video.weex.js
虽然 rax-player 还是叫 rax-player 组件,但是 video.weex.js 实际上导出的是 Video
组件,声明也是 Video
,至于为什么组件起名字的时候是 rax-player
就不得而知了,可能因为 player 比 video 承载的功能更多吧。
1、weex 未来的 videoplus 组件
目前版本(0.6.5)源码中有一段 TODO 如下:
let supportVideoPlus = false;
const weexEnv = typeof WXEnvironment !== 'undefined' ? WXEnvironment : {};
// TODO: rework by feature recognition
if (weexEnv.appName === 'TB' && weexEnv.appVersion) {
let appVersion = weexEnv.appVersion.split('.');
if (appVersion[0] >= 6 && appVersion[1] >= 2) {
supportVideoPlus = true;
}
}
这段代码应该是用在手淘上的,如果 appName 是 TB 并且 WXEnvironment.appVersion
> 6.2
,则会启用 videplus
。
从目前的代码来看 videoplus
应该是一个新的 video 组件,而这个组件则是由 weex 直接提供的,和 video
是同级的。
现在 weex 的源代码中并没有出现该组件,后面应该是会提供,功能相比于 video 会更强大灵活吧,毕竟起名字叫 videoplus 了。
推断会出一个 videplus 组件是基于下面代码猜想(基本上是确定的事情)的:
从下面的代码中也能够看出,videoplus
现在还不完善,还有 bug 存在,所以没有放出来,因为没放出来,所有就不过多的介绍 videoplus 了,无非是一个 video 的强化版。
if (supportVideoPlus) {
VideoComponent = 'videoplus';
props = {
...this.props,
...{
src: videoSrc,
autoPlay: true, // 因为videoplus现在有个bug,当autoPlay不为true的时候埋点会有问题,所有,当视频开始播放之后就设置autoPlay为true
onPaused: this.onVideoPause,
onPlaying: this.onVideoPlay,
onError: this.onVideoFail,
onFinish: this.onVideoFinish,
onLandscape: this.onLandscape,
style: styles.video,
playControl: this.state.pause ? 'pause' : 'play',
}
};
}
2、默认样式及样式重新计算
默认的样式不需要过多的去阐述各个样式的意思,只需要知道,默认的宽度是 750,而默认的高度是 300.(之后肯定回去分析一波 rax 的无单位自动计算是怎么去做的,虽然也是通过 rem 去做,但是对于开发者来说,无单位自动计算数据真的很方便。)
const defaultStyles = {
container: {
position: 'relative',
overflow: 'hidden',
width: 750,
height: 300
},
video: {
width: 750,
height: 300,
zIndex: 1
},
poster: {
overflow: 'hidden',
position: 'absolute',
top: 0,
left: 0,
zIndex: 1,
},
startBtn: {
overflow: 'hidden',
position: 'absolute',
color: '#ffffff',
top: 0,
left: 0,
zIndex: 1
},
startBtnImage: {
width: 109,
height: 111
}
};
上面的代码是默认的样式,而最终 rax-video 组件的样式,是通过 calculateStyle
计算出来的,rax-video 支持通过 props.style
传递 video 的样式,在 calculateStyle
方法中,对 defaultStyles
进行覆盖或者是重计算行为。
其中 defaultStyles.container
和 defaultStyles.video
的宽度和高度均可以通过 props.style.width/props.style.height
进行覆盖,而 startBtn
和 startBtnImage
的样式则需要根据高度或者是宽度进行重新计算,其中 startBtn
只要是根据视频高度计算自身的高度,而 startBtnImage
则主要是计算 marginLeft
和 marginTop
,虽然不是很认可这种通过 marginLeft
和 marginTop
这种方式实现居中和垂直对齐,但是既然 rax 使用了这种方式,想必还有不知道的坑吧。
最后是计算 poster
也就是封面图的相关位置和大小。
calculateStyle() {
let styles = defaultStyles;
styles.container = {
...defaultStyles.container,
...this.props.style
};
styles.video = {
...defaultStyles.video,
...{
width: this.props.style.width || defaultStyles.video.width,
height: this.props.style.height || defaultStyles.video.height
}
};
styles.startBtn = {
...defaultStyles.startBtn,
...{
width: styles.video.width,
height: parseInt(styles.video.height) - 75
}
};
styles.startBtnImage = {
...defaultStyles.startBtnImage,
...{
marginLeft: (parseInt(styles.video.width) - parseInt(defaultStyles.startBtnImage.width)) / 2,
marginTop: (parseInt(styles.video.height) - parseInt(defaultStyles.startBtnImage.height)) / 2
}
};
styles.poster = {
...defaultStyles.poster,
...{
width: styles.video.width,
height: styles.video.height
}
};
styles.posterImage = {
width: styles.video.width,
height: styles.video.height
};
return styles;
}
3、维护的 state
rax-player 本身维护的 state 如下:
state = {
pause: this.props.autoPlay ? false : true,
poster: true,
update: true
};
pause
是维护暂停的状态,如果是自动播放(autoPlay=true
) ,则默认为 true。
poster 是是否有封面图,默认为 true。
4、组件更新生命周期
在性能优化方面,如果开启了 autoPlay = true
,则组件是不会进行更新的,而组件默认也是不会更新。
不过如果传入的是新视频(isNew 是 Video 组件的静态变量,默认为 true)或者主动声明 state.update = true
则会进行组件的更新,并且更新后,直接将 isNew 置为 false,以便于声明不是新的视频。
shouldComponentUpdate(nextProps, nextState) {
if (this.props.autoPlay) {
return false;
}
if ( this.isNew || nextState.update) {
this.isNew = false;
return true;
}
return false;
}
5、播放状态切换 switch()
switch()
方法是当播放状态变更的时候,更改 state,设计的 state 是 update
和 pause
。
switch = (status) => {
this.setState({
pause: status === 'stop',
update: true
});
}
结合上面的组件更新生命周期的方法,可以发现,当视频播放状态发生变动后,组件会进行更新,因此 nextState.update
已经是变成 true 的。
switch()
方法只用在播放按钮 Icon 的 onClick 事件上,其他地方没有使用该方法,其余的状态切换,均在各个事件 handler 中完成。
6、视频暂停
onVideoPause
是当视频暂停时的处理方法,期间会判断是否传入了 props.onVideoPause
,如果存在才会进行调用。
无论是否需要使用 props.onVideoPause
,都会判断此时是否是暂定状态,如果是暂定状态,则 state.update = false
,此时不会进行组件更新。
onVideoPause = (e) => {
typeof this.props.onVideoPause === 'function' && this.props.onVideoPause(e);
if (this.state.pause === false) {
this.setState({
pause: true,
update: false
});
}
};
7、视频播放
onVideoPlay
是视频播放触发时的处理方法,同样如果没有传入 props.onVideoPlay
则只会对 state 进行变动。
同样的,仅仅是触发 onVideoPlay 也不会进行组件更新,state.update 也是 false。
onVideoPlay = (e) => {
typeof this.props.onVideoPlay === 'function' && this.props.onVideoPlay(e);
this.state.poster = false;
if (this.state.pause === true) {
this.setState({
pause: false,
update: false
});
}
};
8、其他的事件Handle
其他的事件 Handle 就不重复了,主要是三个方法 onVideoFail
、onVideoFinish
、 onLandscape
。
如果不传入 props 则不会进行任何的处理。
9、render 方法
render 方法中,第一个变量 videoComponent = 'video'
便是直接证明了 weex 环境下,rax-player 使用的是 weex 的内置 video 组件。
值得注意的是,videoSrc
将传递过来的视频地址的 schema 直接干掉,全部使用 //xxx.mp4
。
至于渲染的方法,还是挺简单的,如果对上面各个流程和变量熟悉了,渲染的方法无非就是 View 加上 video 组件,其中可能还包括 poster
封面图等内容。
return <View style={styles.container}>
{
poster && playStatus == 'stop' ?
null :
<VideoComponent
{...props}
/>
}
{ playStatus == 'stop' && poster && this.state.poster && <View
style={styles.poster}
ref="poster"
>
<Image
source={{
uri: poster
}}
style={styles.posterImage}
/>
</View>
}
{ playStatus == 'stop' && this.props.startBtn && <View
style={styles.startBtn}
ref="starBtn"
>
<Image
source={{
uri: 'https://gw.alicdn.com/tps/TB1FxjDKFXXXXcRXVXXXXXXXXXX-109-111.png'
}}
style={styles.startBtnImage}
onClick={() => {
this.switch(!playStatus);
}}
/>
</View>
}
</View>;
}
在 render 方法中,将 weex 的默认视频播放组件 video
赋值给了 VideoComponent
变量,是因为我最前面提到的,如果支持 videoplus,则会将 videoplus 赋值给 VideoComponent,从而做到兼容性。
三、weex 容器下的效果
文章版权:Postbird-There I am , in the world more exciting!
本文链接:http://www.ptbird.cn/rax-player-weex.html
转载请注明文章原始出处 !