音量调节条-封装通用的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 树控件使用经验分享,这篇里面第 ...
随机推荐
- [Web前端] WEEX、React-Native开发App心得 (转载)
转自: https://www.jianshu.com/p/139c5074ae5d 2018 JS状态报告: https://2018.stateofjs.com/mobile-and-deskto ...
- GWAS 全基因组关联分析 | summary statistic 概括统计 | meta-analysis 综合分析
有很多概念需要明确区分: 人有23对染色体,其中22对常染色体autosome,另外一对为性染色体sex chromosome,XX为女,XY为男. 染色体区带命名:在标示一特定的带时需要包括4项:① ...
- Confluence 实现公司wiki【转】
Confluence是一个企业级的Wiki软件,可用于在企业.部门.团队内部进行信息共享和协同编辑一.安装过程1 安装并配置mysql [root@vm1 ~]# /etc/my.cnf charac ...
- MiniUI表单验证实践
学习实践: <form id="form2"> <div id="update_pas" style="width:380px&qu ...
- Python判断是否是闰年
year = 2012 if year % 100 != 0 and year % 4 == 0: print('闰年') elif year % 100 == 0 and year % 400 == ...
- HBase在特征工程中的应用
前言HBase是一款分布式的NoSQL DB,可以轻松扩展存储和读写能力. 主要特性有: 按某精确的key获取对应的value(Get) 通过前缀匹配一段相邻的数据(Scan) 多版本 动态列 服务端 ...
- Python3基础 只有int类型,没有long类型
Python : 3.7.3 OS : Ubuntu 18.04.2 LTS IDE : pycharm-community-2019.1.3 ...
- idea 配置文件中文显示问题
配置文件中的中文,有时候会显示异常,因此需要修改文件编码格式修改.下面红框位置需要勾选上.
- Form表单的传递与接收
目录 表单的构建 后端接收 创建model 用Model接收表单的后端 表单的构建 我才知道这个东西,在开发中经常遇到表单的情况.一下子提交一串内容.表单元素 form,里面的内容必须有name字段. ...
- 网络编程之Reactor 模式
基本的架构是 epoll+线程池. 这篇博文主要从以下几个方面进行阐述: (1)reactor模式的一个介绍:(只要是我的理解) (2)关于线程池的说明. (3)如何将epoll + 池结合起来实现一 ...