音量调节条-封装通用的ProgressBar组件
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import assign from 'object-assign'
import _ from 'lodash'
import CX from 'classnames'
import './index.less'
/**
* ProgressBar
* vertical 设置进度条是否垂直显示
* trackHover trackHover事件
* onSlide 事件函数获取percent值
* percent 设置滑块位置,0~100之间
* style 最外层div的样式
* slidedStyle 滑块左侧划过部分的样式
* trackStyle 滑块右侧未划过部分的样式
* ballStyle 滑块的样式
* showHoverStyle 是否设置hover时的样式
* hoverStyle 最外层div的样式
* hoverSlidedStyle 滑块左侧划过部分的样式
* hoverTrackStyle 滑块右侧未划过部分的样式
* hoverBallStyle 滑块的样式
* dragInfo 滑动滑块时显示在滑块上方的提示信息,默认没有提示信息
* dragInfoWrapStyle 滑块提示信息父级元素的样式,可用于调整提示信息的位置
* previewInfo 指针在进度条内时显示的指针位置进度提示信息
* previewInfoWrapStyle previewInfo 提示信息父级元素的样式,可用于调整提示信息的位置
* onCursorSlide 事件函数获取当前指针处的percent 可用于更新previewInfo
*/
class ProgressBar extends Component {
static propTypes = {
vertical: PropTypes.bool,
onSlide: PropTypes.func,
style: PropTypes.object,
slidedStyle: PropTypes.object,
trackStyle: PropTypes.object,
ballStyle: PropTypes.object,
showHoverStyle: PropTypes.bool,
hoverStyle: PropTypes.object,
hoverSlidedStyle: PropTypes.object,
hoverTrackStyle: PropTypes.object,
hoverBallStyle: PropTypes.object,
percent: PropTypes.number,
dragInfo: PropTypes.element,
dragInfoWrapStyle: PropTypes.object,
previewInfo: PropTypes.element,
previewInfoWrapStyle: PropTypes.object,
onCursorSlide: PropTypes.func,
disableSlide: PropTypes.bool,
}
static defaultProps = {
vertical: false,
onSlide: _.noop,
style: {},
slidedStyle: {},
trackStyle: {},
ballStyle: {},
showHoverStyle: false,
hoverStyle: {},
hoverSlidedStyle: {},
hoverTrackStyle: {},
hoverBallStyle: {},
percent: 0,
dragInfo: null,
dragInfoWrapStyle: {},
previewInfo: null,
previewInfoWrapStyle: {},
onCursorSlide: _.noop,
disableSlide: false,
}
state = {
percent: this.props.percent,
cursorPercent: 0,
moveFlag: false,
cursorInSlideBall: false,
cursorInComponent: false,
}
componentDidMount() {
this.rangeSlideElem.addEventListener('mousedown', this.onWrapElemMouseDown)
this.rangeSlideElem.addEventListener('mouseenter', this.onWrapElemMouseEnter)
this.rangeSlideElem.addEventListener('mousemove', this.onWrapElemMouseMove)
this.rangeSlideElem.addEventListener('mouseleave', this.onWrapElemMouseLeave)
this.rangeSlideElem.addEventListener('click', this.handleSlide)
document.body.addEventListener('mousemove', this.onBodyMouseMove)
document.body.addEventListener('mouseup', this.onBodyMouseUp)
document.body.addEventListener('mouseleave', this.onBodyMouseLeave)
}
componentWillReceiveProps(nextProps) {
if (nextProps.percent !== this.props.percent) {
this.setState({
percent: nextProps.percent,
})
}
}
componentWillUnmount() {
document.body.removeEventListener('mousemove', this.onBodyMouseMove)
document.body.removeEventListener('mouseup', this.onBodyMouseUp)
document.body.removeEventListener('mouseleave', this.onBodyMouseLeave)
}
getPercent = (e) => {
let percentage
if (this.props.vertical === false) {
const offsetLeft = this.rangeSlideElem.getBoundingClientRect().x
const { offsetWidth } = this.rangeSlideElem
percentage = Math.round(((e.pageX - offsetLeft) / offsetWidth) * 100)
} else {
const offsetTop = this.rangeSlideElem.getBoundingClientRect().y
const { offsetHeight } = this.rangeSlideElem
percentage = Math.round((1 - (e.pageY - offsetTop) / offsetHeight) * 100)
}
percentage = Math.max(Math.min(percentage, 100), 0)
return percentage
}
onWrapElemMouseDown = () => {
this.setState({
moveFlag: true,
})
}
onBodyMouseMove = _.throttle((e) => {
if (this.state.moveFlag) {
this.handleSlide(e)
}
}, 30)
onBodyMouseUp = () => {
this.setState({
moveFlag: false,
})
}
onBodyMouseLeave = this.onBodyMouseUp
handleSlide = (e) => {
if (this.props.disableSlide === true) {
return
}
const percent = this.getPercent(e)
this.props.onSlide(percent)
this.setState({
percent,
})
}
onSlideBallMouseEnter = () => {
this.setState({
cursorInSlideBall: true,
})
}
onSlideBallMouseLeave = () => {
this.setState({
cursorInSlideBall: false,
})
}
onWrapElemMouseEnter = (e) => {
const cursorPercent = this.getPercent(e)
this.props.onCursorSlide(cursorPercent)
this.setState({
cursorInComponent: true,
cursorPercent,
})
}
onWrapElemMouseMove = (e) => {
const cursorPercent = this.getPercent(e)
this.props.onCursorSlide(cursorPercent)
this.setState({
cursorPercent,
})
}
onWrapElemMouseLeave = () => {
this.setState({
cursorInComponent: false,
})
}
rangeSlideElem
activeBarElem
render() {
const { cursorInComponent } = this.state
const showHoverStyle = cursorInComponent && this.props.showHoverStyle
const wrapStyles = assign({}, showHoverStyle ? this.props.hoverStyle : this.props.style)
let slideTrackStyles
if (this.props.vertical === true) {
slideTrackStyles = assign({}, showHoverStyle ? this.props.hoverTrackStyle : this.props.trackStyle, {
height: `${100 - this.state.percent}%`,
})
} else {
slideTrackStyles = assign({}, showHoverStyle ? this.props.hoverTrackStyle : this.props.trackStyle, {
width: `${100 - this.state.percent}%`,
})
}
const activeBarStyles = assign({}, showHoverStyle ? this.props.hoverSlidedStyle : this.props.slidedStyle)
const slideBallStyles = assign({}, showHoverStyle ? this.props.hoverBallStyle : this.props.ballStyle)
const dragInfoWrapStyle = assign({}, this.props.dragInfoWrapStyle)
const previewInfoWrapStyle = assign({}, this.props.previewInfoWrapStyle, {
left: `${this.state.cursorPercent}%`,
})
const showDragInfo = this.state.cursorInSlideBall || this.state.moveFlag
const showPreviewInfo = showDragInfo === false && this.state.cursorInComponent
return (
<div
className={CX({
'horizontal-progress-bar-component-wrap': this.props.vertical === false,
'vertical-progress-bar-component-wrap': this.props.vertical === true,
})}
style={wrapStyles}
ref={(r) => {
this.rangeSlideElem = r
}}
>
<div className="active-bar" style={activeBarStyles} />
<div
className="slide-track"
ref={(r) => {
this.activeBarElem = r
}}
style={slideTrackStyles}
>
<div
className="slide-ball"
style={slideBallStyles}
onMouseEnter={this.onSlideBallMouseEnter}
onMouseLeave={this.onSlideBallMouseLeave}
/>
{
showDragInfo && (
<div
className="drag-info-element-wrap"
style={dragInfoWrapStyle}
>
{this.props.dragInfo}
</div>
)
}
</div>
{
showPreviewInfo && (
<div
className="preview-info-element-wrap"
style={previewInfoWrapStyle}
>
{this.props.previewInfo}
</div>
)
}
</div>
)
}
}
export default ProgressBar
样式如下:
.horizontal-progress-bar-component-wrap {
width: 100%;
height: 12px;
margin:;
position:relative;
cursor: pointer;
.active-bar {
position:absolute;
top: 50%;
left:;
margin-top: -2px;
width: 100%;
height: 4px;
border-radius: 4px;
background: linear-gradient(to right, #81d5fa, #3977f6);
}
.slide-track {
width: 50%;
height: 4px;
position:absolute;
top: 50%;
right:;
margin-top: -2px;
border-radius: 4px;
background: #fff;
.slide-ball {
width: 12px;
height: 12px;
position: absolute;
left: -6px;
top: -4px;
border-radius: 50%;
cursor: pointer;
background: url('~ROOT/shared/assets/image/vn-circle-blue-42-42.png') no-repeat center;
background-size: 12px;
}
.drag-info-element-wrap {
position: absolute;
left: -24px;
top: -46px;
}
}
.preview-info-element-wrap {
position: absolute;
top: -32px;
margin-left: -24px;
}
}
.vertical-progress-bar-component-wrap {
width: 12px;
height: 100%;
margin:;
position: relative;
cursor: pointer;
.active-bar {
position:absolute;
bottom:;
left: 50%;
margin-left: -2px;
height: 100%;
width: 4px;
border-radius: 4px;
background: linear-gradient(to top, #81d5fa, #3977f6);
}
.slide-track {
position:absolute;
height: 50%;
width: 4px;
right: 50%;
top: -2px;
margin-right: -2px;
border-radius: 4px;
background: #fff;
.slide-ball {
width: 12px;
height: 12px;
position: absolute;
left: -4px;
bottom: -6px;
border-radius: 50%;
cursor: pointer;
background: url('~ROOT/shared/assets/image/vn-circle-blue-42-42.png') no-repeat center;
background-size: 12px;
}
.drag-info-element-wrap {
position: absolute;
left: -46px;
bottom: -24px;
}
}
.preview-info-element-wrap {
position: absolute;
left: -32px;
margin-bottom: -24px;
}
}
音量调节条-封装通用的ProgressBar组件的更多相关文章
- 【Ubuntu日常技巧】【解决】Ubuntu 16 右上角的音量调节通知框不停地闪烁问题
一. 先上干货 解决问题 1.1 安装工具alsa-tools-gui sudo apt-get install alsa-tools-gui 1.2 通过hdajackretask设置 直接执行命令 ...
- 如何通过 Vue+Webpack 来做通用的前端组件化架构设计
目录: 1. 架构选型 2. 架构目录介绍 3. 架构说明 4. 招聘消息 目前如果要说比较流行的前端架构哪家强,屈指可数:reactjs.angularjs.emberj ...
- 第二百四十一节,Bootstrap进度条媒体对象和 Well 组件
第二百四十一节,Bootstrap进度条媒体对象和 Well 组件 学习要点: 1.Well 组件 2.进度条组件 3.媒体对象组件 本节课我们主要学习一下 Bootstrap 的三个组件功能:Wel ...
- Android、iOS平台RTMP/RTSP播放器实时音量调节
介绍移动端RTMP.RTSP播放器实时音量调节之前,我们之前也写过,为什么windows播放端加这样的接口,windows端播放器在多窗口大屏显示的场景下尤其需要,尽管我们老早就有了实时静音接口,相对 ...
- Windows平台RTMP/RTSP播放器实现实时音量调节
为什么要做实时音量调节 RTMP或RTSP直播播放音量调节,主要用于多实例(多窗口)播放场景下,比如同时播放4路RTMP或RTSP流,如果音频全部打开,几路audio同时打开,可能会影响用户体验,我们 ...
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)
前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...
- C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper
前言:之前学习过很多的Bootstrap组件,博主就在脑海里构思:是否可以封装一套自己Bootstrap组件库呢.再加上看到MVC的Razor语法里面直接通过后台方法输出前端控件的方式,于是打算仿照H ...
- JS组件系列——封装自己的JS组件,你也可以
前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...
- JS组件系列——分享自己封装的Bootstrap树形组件:jqTree
前言:之前的一篇介绍了下如何封装自己的组件,这篇再次来体验下自己封装组件的乐趣.看过博主博客的园友应该记得之前分享过一篇树形菜单的使用JS组件系列——Bootstrap 树控件使用经验分享,这篇里面第 ...
随机推荐
- python 处理geoJson to shp 互转
- P1310 表达式的值
P1310 表达式的值 题解 1.假设有两个布尔变量 x , y x0表示使得x=0的方案数 x1表示使得x=1的方案数 y0表示使得y=0的方案数 y1表示使得y=1的方案数 | 按位或 & ...
- laravel打印sql所执行的原生语句
DB::listen(function($sql) { foreach ($sql->bindings as $i => $binding) { if ($binding instance ...
- intel 性能分析
分析memory bound,etc https://software.intel.com/en-us/articles/intel-vtune-amplifier-tutorials
- SSIM (Structural SIMilarity) 结构相似性
公式基于样本x和 y 之间的三个比较衡量:亮度 (luminance).对比度 (contrast) 和结构 (structure). 每次计算的时候都从图片上取一个 N*N的窗口,然后不断滑动窗口进 ...
- postgresql 利用pgAgent实现定时器任务
1.安装pgAgent 利用Application Stack Builder安装向导,安装pgAgent. 根据安装向导一步一步安装即可. 安装完成之后,windows服务列表中会增加一个服务:Po ...
- Spring cloud微服务安全实战-5-5实现授权码认证流程(1)
目前为止已经完成了完整的用户逻辑 目前的问题是,用户在登陆的时候,用户名提交的是给前端服务器的.每个前端服务器的开发人员都可能接触到前端的用户名密码. 每一个客户端应用都要去处理登陆的逻辑,一单我的登 ...
- C++数据存储方式
1.栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区,里面的变量通常是局部变量.函数参数等. 2.堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去 ...
- doris: shell invoke .sql script for doris and passing values for parameters in sql script.
1. background in most cases, we want to execute sql script in doris routinely. using azkaban, to l ...
- centos7 gcc升级
1. 安装必备 yum groupinstall "Development Tools" yum install glibc-static libstdc++-static 2 ...