音量调节条-封装通用的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 树控件使用经验分享,这篇里面第 ... 
随机推荐
- win10创建Ubuntu16.04子系统,安装常用软件以及图形界面(包括win10远程桌面连接Ubuntu)
			一.开启win10子系统 [ Windows Subsystem for Linux(WSL)] 二.基本配置 三.安装常用的软件 安装配置zsh 使用 bash 客户端软件 cmder(其实是win ... 
- pytorch 想在一个优化器中设置多个网络参数的写法
			使用tertools.chain将参数链接起来即可 import itertools ... self.optimizer = optim.Adam(itertools.chain(self.enco ... 
- TLS握手协议分析与理解——某HTTPS请求流量包分析
			https://xz.aliyun.com/t/1039 HTTPS简介 HTTPS,是一种网络安全传输协议,在HTTP的基础上利用SSL/TLS来对数据包进行加密,以提供对网络服务器的身份认证,保护 ... 
- Spring cloud微服务安全实战-5-4请求转发及退出
			步骤1234已经完成 下面处理 5678这几步.zuul在转发的时候 把请求头加上 获取订单信息 加一个按钮,登陆成功后,去拿订单的信息. 展示获取到的订单信息 ts代码 ts内定义order对象 定 ... 
- 123457123456#0#----com.DoraGame.YingYu65--前拼后广--儿童英语doraX
			com.DoraGame.YingYu65--前拼后广--儿童英语doraX 
- delphi十六进制字符串hex转byte数组互相转换bmp图片
			procedure Hex2Png(str: string; out png: TPngObject); var stream: TMemoryStream; begin if not Assigne ... 
- 关于IO的操作(文件、网络)
			IO操作的流程总结和分析: (1)对象,易于编写代码 ---> (2)byte[],底层本质 ----> (3)IO(文件.网络),最终IO处理掉 
- 亲爱的mssql码农们,看看利用sp_addlinkedserver实现远程数据库链接
			亲爱的mssql码农们,可以看看本地连接远程的数据库方式(sp_addlinkedserver)--通过代码连接 --查看当前链接情况: select * from sys.servers; --使用 ... 
- angular2 select 联动
			界面操作触发大分类id改变,根据id获取二级分类的数据进行绑定显示. html: <div style="overflow: hidden;float: left;padding-le ... 
- 在ensp上配置通过Stelnet登录系统
			我们为什么我们要采用Stelent登录? 因为不安全,我们要采用更加安全的方式,双向加密,通过ssh网络安全协议 下面我们开始实验:使用路由器R1模拟PC,作为SSH的客户端:路由器R2作为SSH的服 ... 
