音量调节条-封装通用的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 树控件使用经验分享,这篇里面第 ...
随机推荐
- flink 读JDQ和写JDQ的流程
ReadFromJDQ3 1)消费JDQ的必要信息,通过参数传入,有6个参数 2)获取flink JDQ3的鉴权客户端 3)根据鉴权客户端获取消费属性的配置 4)构建应用环境ENV和checkpoin ...
- k8s 集群部署--学习
kubernetes是google开源的容器集群管理系统,提供应用部署.维护.扩展机制等功能,利用kubernetes能方便管理跨集群运行容器化的应用,简称:k8s(k与s之间有8个字母) Pod:若 ...
- linux下的/dev/shm/及对Oracle 的影响
一./dev/shm/介绍: /dev/shm/是linux下一个非常有用的目录,因为这个目录不在硬盘上,而是在内存里.因此在linux下,就不需要大费周折去建ramdisk,直接使用/dev/shm ...
- nice -n 10 bash 和 chrt 10 bash 和 echo -17 > /proc/PID/oom_score_adj
进程优先级起作用的方式从发明以来基本没有什么变化,无论是只有一个cpu的时代,还是多核cpu时代,都是通过控制进程占用cpu时间的长短来实现的. 就是说在同一个调度周期中,优先级高的进程占用的时间长些 ...
- RabbitMQ教程C#版 - 发布订阅
先决条件本教程假定 RabbitMQ 已经安装,并运行在localhost标准端口(5672).如果你使用不同的主机.端口或证书,则需要调整连接设置. 从哪里获得帮助如果您在阅读本教程时遇到困难,可以 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#region(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#region(C# 参考) 1.返回顶部 1. #region(C# 参考) 2015/07/20 利用 #region,可以 ...
- asp乱码问题
UTF-8编码的话:在ASP脚本顶部加入<%@Language="vbscript" Codepage="65001"%>以及再在<head& ...
- datax实例——全量、增量同步
一.全量同步 本文以mysql -> mysql为示例: 本次测试的表为mysql的系统库-sakila中的actor表,由于不支持目的端自动建表,此处预先建立目的表: CREATE TABLE ...
- vs webapi 取消controller
1.添加引用 using Panda.DynamicWebApi; 2.starup.cs public void ConfigureServices(IServiceCollection servi ...
- java使用Sonic 算法对音频变速不变声、变调、调整音量
依赖库:https://github.com/waywardgeek/sonic 基础库:Sonic.java /* Sonic library Copyright 2010, 2011 Bill C ...