zent
Version:
一套前端设计语言和基于React的实现
148 lines (135 loc) • 3.84 kB
JavaScript
import React, { Component, PureComponent } from 'react';
import WindowEventHandler from 'utils/component/WindowEventHandler';
import keys from 'lodash/keys';
import map from 'lodash/map';
import noop from 'lodash/noop';
import classNames from 'classnames';
import { getLeft, toFixed, checkValueInRange } from './common';
import ToolTips from './toolTips';
export default class Points extends (PureComponent || Component) {
constructor(props) {
super(props);
const { range, value } = props;
this.state = {
visibility: false,
conf: range ? { start: value[0], end: value[1] } : { simple: value }
};
}
getLeft = point => {
const { max, min } = this.props;
return getLeft(point, max, min);
};
isLeftButton = e => {
e = e || window.event;
const btnCode = e.button;
return btnCode === 0;
};
handleMouseDown = (type, evt) => {
evt.preventDefault();
if (this.isLeftButton(evt)) {
this.left = evt.clientX;
this.setState({ type, visibility: true });
let { value } = this.props;
if (type === 'start') {
value = value[0];
} else if (type === 'end') {
value = value[1];
}
this.value = value;
return false;
}
};
getAbsMinInArray = (array, point) => {
const abs = array.map(item => Math.abs(point - item));
let lowest = 0;
for (let i = 1; i < abs.length; i++) {
if (abs[i] < abs[lowest]) {
lowest = i;
}
}
return array[lowest];
};
left = null;
handleMouseMove = evt => {
const left = this.left;
if (left !== null) {
evt.preventDefault();
const { type } = this.state;
const {
max,
min,
onChange,
getClientWidth,
step,
dots,
marks,
range
} = this.props;
let newValue = (evt.clientX - left) / getClientWidth();
newValue = (max - min) * newValue;
newValue = Number(this.value) + Number(newValue);
if (dots) {
newValue = this.getAbsMinInArray(keys(marks), newValue);
} else {
newValue = Math.round(newValue / step) * step;
}
newValue = toFixed(newValue, step);
newValue = checkValueInRange(newValue, max, min);
let { conf } = this.state;
conf[type] = newValue;
this.setState({ conf });
onChange && onChange(range ? [conf.start, conf.end] : newValue);
}
};
handleMouseUp = () => {
this.left = null;
this.setState({ visibility: false });
};
componentWillReceiveProps(props) {
const { range, value } = props;
if (this.left === null) {
this.setState({
conf: range ? { start: value[0], end: value[1] } : { simple: value }
});
}
}
render() {
const { visibility, type, conf } = this.state;
const { disabled, prefix } = this.props;
return (
<div className={`${prefix}-slider-points`}>
{map(conf, (value, index) => (
<ToolTips
prefix={prefix}
key={index}
content={value}
visibility={index === type && visibility}
left={this.getLeft(value)}
>
<span
onMouseDown={
!disabled ? this.handleMouseDown.bind(this, index) : noop
}
className={classNames(
{ [`${prefix}-slider-point-disabled`]: disabled },
`${prefix}-slider-point`
)}
/>
</ToolTips>
))}
{!disabled && (
<WindowEventHandler
eventName="mousemove"
callback={this.handleMouseMove}
/>
)}
{!disabled && (
<WindowEventHandler
eventName="mouseup"
callback={this.handleMouseUp}
/>
)}
</div>
);
}
}