音量调节条-封装通用的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 树控件使用经验分享,这篇里面第 ...
随机推荐
- MySQL枚举类型enum字段在插入不在指定范围的值时, 是否是"插入了enum的第一个值"?
刚刚在看<<深入浅出MySQL>>一书的"ENUM类型"一节, 以下面的代码举例, 得出结论: "还可以看出对于不在ENUM指定范围内的值时, 并 ...
- JVM 数组创建的本质
1.创建数组 创建一个MyParent4[] 数组 public class MyTest4 { public static void main(String[] args) { MyParent4[ ...
- linux下的/dev/shm/及对Oracle 的影响
一./dev/shm/介绍: /dev/shm/是linux下一个非常有用的目录,因为这个目录不在硬盘上,而是在内存里.因此在linux下,就不需要大费周折去建ramdisk,直接使用/dev/shm ...
- vbs msgbox提示信息最前面显示
msgbox strContent, vbOKOnly or vbExclamation or vbSystemModal,strTitle 提示框类型列表: 常数 值 描述 vbOKOnly 0 只 ...
- ntpd服务
yum -y install ntp 服务器端 [root@ip-172-31-6-148~]# vim /etc/ntp.conf ...# Use public servers from thep ...
- uefi下如何启动linux?
1. 有两种方式 1.1 直接从uefi shell启动linux内核 1.2 从uefi shell启动grub,然后再从grub启动linux内核 2. 需要哪些东西? 2.1 linux内核 2 ...
- Andorid SQLite数据库开发基础教程(3)
Andorid SQLite数据库开发基础教程(3) 数据库生成方式 数据库的生成有两种方式,一种是使用数据库管理工具生成的数据库,我们将此类数据库称为预设数据库,另一种是使用代码生成的数据库. 使用 ...
- Flutter响应式编程 - RxDart
import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; import 'dart:async'; cl ...
- Flutter ListView 列表组件
列表常见的情况: 1.垂直列表 2.垂直图文列表 3.横向列表 4.动态列表 名称 类型 说明 scrollDirection Axis Axis.horizontal 横向列表 Axis.verti ...
- postgresql 所有聚合函数整理
SELECT DISTINCT(proname) FROM pg_proc WHERE proisagg order by proname 查所有 SELECT * FROM pg_proc WHER ...