Slider主要的API如下:
属性 | 类型 | 说明 |
---|---|---|
defaultValue | number | 默认值 |
tickValue | number | 标尺刻度数量,默认5 |
start | number | 起始值,默认值为0 |
end | number | 结束值 |
suffix | string | 后缀 |
onSliding | func | 滑块拖动进行时事件,value为拖动条当前值 |
onSlid | func | 滑块拖动完成时事件,即鼠标抬起后执行,value为拖动条当前值 |
defaultValue就是默认的拖动条的位置,tickValue是有多少段,start和end分别是起始和结束刻度,suffix是后缀。
Slider组件的包括几个基础子组件:slider,selectedBar,Scale
slider是拖动的头部区域,就是那个方块和tooltip
selectedBar是蓝色区域,不包括slider,是已选择的区域
Scale是下面的刻度区域
bar是整个的灰色线条区域
刻度:
刻度的实现就是创建一个数组,用来存储每个刻度div(一个刻度就是一个div),然后通过遍历来给每一个刻度赋值(value)和给style.left赋值,这样刻度条按照特定的位置排列。
class Scale extends Component { constructor() { super() } componentWillMount() { this.tickValue = this.props.tickValue || 5 } render() { const {width} = this.props const rows = [] for (let i = 0; i <= this.tickValue; i++) { rows.push({i}) } return ({rows}) } componentDidMount() { const container = this.refs.container const containerStyle = getComputedStyle(container) const width = parseInt(containerStyle.width) const scope = this.props.end - (this.props.start || 0) this.width = width this.scope = scope const arr = this.getTick(this.tickValue) arr.map((tick, index) => { let value = scope / width * tick + this.props.start if (index == 0) { value = this.props.start } if (index == arr.length - 1) { value = this.props.end } const el = this.refs['t' + index] s el.innerHTML = ' ' + parseInt(Math.round(value)) if (index == 0) { el.style.left = 4 + 'px' } else if (index == this.tickValue) { el.style.left = parseInt(tick) - 1 + 'px' } else { el.style.left = tick + 'px' } }) } getTick(num) { const arr = [] num = !num ? 1 : num const w = this.width / num for (let i = 0; i < num; i++) { arr.push(i * w) } arr.push(this.width)`` return arr }}复制代码
slider区域
slider区域是整个组件逻辑所在的地方,主要是该组件绑定了mouseDown事件,而mousedown事件中为body绑定了mousemove和mouseup事件,我们的逻辑主要在mousemove事件中,在mousedown事件和mouseup事件响应函数中主要是为body注册和卸载事件监听器。我们来看mousemove事件的监听函数:
handleMouseMove(event) { const slider = this.refs.slider const selectedBar = this.refs.selectedBar const bar = this.refs.bar this.offsetLeft = this.getOffsetLeft(bar) + this.marginLeft if (this.isDown) { let left = event.pageX - this.offsetLeft - this.sliderWidth / 4 if (left <= 0) { left = 0 selectedBar.style.width = left + 'px' } else if (left >= (this.width - this.sliderWidth / 2)) { left = this.width - this.sliderWidth / 2 selectedBar.style.width = this.width + 'px' } else { selectedBar.style.width = left + 'px' } slider.style.left = left + 'px' const text = this.getValue(parseInt(selectedBar.style.width, 10)) this.refs.msg.innerHTML = text + (this.props.suffix || '') if (typeof this.props.onSliding == 'function') { this.props.onSliding(text) } } }复制代码
可以看到,上面主要是设置selectBar的宽度selectedBar.style.width
,设置msg中的文本text
,如果组件设置了onSiding处理函数的话,就触发该函数。
代码中有一个封装较好的函数,用来获取一个元素的左偏移量
getOffsetLeft(el) { let left = 0 let offsetParent = el while (offsetParent != null && offsetParent != document.body) { left += offsetParent.offsetLeft offsetParent = offsetParent.offsetParent } return left }复制代码