实现的效果图如下:
如果所示,点击播放按钮可以播放,进度条表示进度
功能描述:
1. 点击播放按钮可以播放,进度条表示进度
2. 点击暂停,进度条停止变化
3. 可点击圆点,进行进度拖拽
4. 点击进度条可调节进度
以下是render部分代码:
<div className="play" ref={play => { this.play = play; }}>
<span className="palyButton" onClick={this.handlePlay}><Icon type="caret-right" style={{ display: this.state.autoPlay ? 'none' : 'inline-block' }} /><Icon type="pause" style={{ display: this.state.autoPlay ? 'inline-block' : 'none' }} /></span>
<span className="lineWrap" onMouseMove={this.handleMouseMove} onMouseUp={this.handleMouseUp} onMouseLeave={this.handleMouseUp} onClick={this.clcikLine} ref={line => { this.line = line; }}>
<span className="lineInner" ref={inner => { this.inner = inner; }}>
<span className="lineDot" onMouseDown={this.handleMouseDown} ref={dot => { this.dot = dot; }} />
</span>
</span>
</div>
定义一个最大的div来包裹播放按钮和进度条:
播放按钮是两个antd的icon,通过state中的autoPlay来控制显示哪一个icon
进度条的中定义一个外span,是进度条的总长度,在这个span里定义一个span,是中间的滑块,再定义一个span是可拖拽的圆点
以下是这部分的css样式代码,只要小圆点使用的绝对定位:
.play{
width: 100%;
height: 30%;
padding: 0 40px;
margin-top: 15px;
.palyButton{
margin-right: 22px;
cursor: pointer;
color: #1DDD92;
font-size: 20px;
i:last-child{
font-weight: bold;
}
}
.lineWrap{
width: 95%;
height: 14px;
background-color: #2A2F4D;
display: inline-block;
cursor: pointer;
.lineInner{
width: 10%;
height: 100%;
display: inline-block;
background-color: #1DDD92;
position: relative;
.lineDot{
position: absolute;
top: -3px;
right: -10px;
width: 20px;
height: 20px;
display: inline-block;
background-color: #1DDD92;
border: 1px solid #fff;
border-radius: 50%;
}
}
}
}
功能实现的思想:
1. 点击进度条可以实现进度调整
原理:点击进度条获取点击事件的pageX属性,然后通过减去进度条左边的margin来计算点击的进度条的位置,因为整个页面的左边有一个tab切换,这个tab切换可以被隐藏,所以整个进度条的宽度是不定的,所以进度条的滑块要使用百分比来实现,保证在进度条总宽度变化时滑块的宽度按比例变化:
clcikLine = e => {
const len = this.line.clientWidth / 24;
// 将整个进度条分为24份
const windowWidth = window.innerWidth - this.line.clientWidth - this.line.offsetLeft - 20;
let lineWidth;
if (windowWidth > 240) {
// 当导航显示时,计算整个滑块的宽度要减去导航的宽度240px
lineWidth = e.pageX - this.line.offsetLeft - 240;
} else {
lineWidth = e.pageX - this.line.offsetLeft;
}
// 将最终的滑块宽度按百分比进行转换
const innerWidth = Math.round(lineWidth / len);
this.inner.style.width = 100 / 24 * innerWidth + '%';
}
2. 点击播放,进度增加,点击暂停,进度停止
handlePlay = () => {
// 设置播放按钮
this.setState({
autoPlay: !this.state.autoPlay,
});
// 清楚定时器
clearInterval(this.timer);
setTimeout(() => {
if (this.state.autoPlay) {
const wrapWidth = this.line.clientWidth;
const innerWidth = this.inner.clientWidth;
if (innerWidth < wrapWidth) {
this.timer = setInterval(() => {
// 设置定时器,每1000毫秒执行一次,每1000毫秒滑块长度增加进度条的1%长度
this.inner.style.width = Math.round(this.inner.clientWidth / this.line.clientWidth * 100) + 1 + '%';
// 每次获得的增加的百分比长度都进行四舍五入
if (this.inner.clientWidth >= this.line.clientWidth) {
// 当滑块的长度大于等于进度条的长度时,清楚定时器,并且关闭播放按钮
clearInterval(this.timer);
this.setState({
autoPlay: false
});
}
}, 1000);
} else {
// 当滑块宽度大于进度条宽度时,点击播放按钮,延时1000毫秒自动关闭播放按钮
setTimeout(() => {
this.setState({
autoPlay: false
});
}, 1000);
}
}
}, 20);
}
3. 圆点可以拖拽,调整进度条进度
这个功能中,使用了四个事件,分别是:onMouseMove、onMouseUp、onMouseLeave放在进度条上,onMouseDown放在可拖拽的圆点上。
handleMouseDown = e => {
// 鼠标按下时打开可拖功能
this.setState({
drag: true,
});
}
handleMouseMove = e => {
// 当可拖拽功能打开时
if (this.state.drag) {
// 滑块宽度小于进度条宽度或大于0时
if (this.inner.clientWidth <= this.line.clientWidth || this.inner.clientWidth <= 0) {
// 将进度条分为200份
const len = this.line.clientWidth / 200;
// 判断导航是否隐藏
const windowWidth = window.innerWidth - this.line.clientWidth - this.line.offsetLeft - 20;
let lineWidth;
if (windowWidth > 240) {
// 导航未隐藏
lineWidth = e.pageX - this.line.offsetLeft - 240;
} else {
// 导航隐藏
lineWidth = e.pageX - this.line.offsetLeft;
}
const innerWidth = Math.round(lineWidth / len);
// 滑块宽度每次增加或减少0.5%的宽度
this.inner.style.width = 0.5 * innerWidth + '%';
}
}
}
handleMouseUp = e => {
// 当鼠标放开或者离开进度条时关闭拖拽功能
this.setState({
drag: false,
});
}
以上基本实现了这个功能,播放这一块还会再加东西,后期再加入