mirror of
https://github.com/wassname/slider.git
synced 2026-09-10 12:38:09 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7525de1f1a | ||
|
|
856bdef4ea | ||
|
|
bb41b82b59 | ||
|
|
a428cd3335 | ||
|
|
c021cadcbb | ||
|
|
4a59745a23 | ||
|
|
3e78e9ac4a | ||
|
|
82179e613a | ||
|
|
0a6fb5a570 | ||
|
|
53aa61faf2 |
@@ -56,8 +56,8 @@ require('rc-slider/assets/index.css');
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var Rcslider = require('rc-slider');
|
||||
ReactDOM.render(<Rcslider />, container);
|
||||
var Slider = require('rc-slider');
|
||||
ReactDOM.render(<Slider />, container);
|
||||
```
|
||||
|
||||
## API
|
||||
@@ -168,7 +168,7 @@ ReactDOM.render(<Rcslider />, container);
|
||||
<td>tipFormatter</td>
|
||||
<td>function or `null`</td>
|
||||
<td></td>
|
||||
<td>Format the value of the tooltip if it shows. If `null` the tooltip will always be hidden.</td>
|
||||
<td>Format the value of the tooltip if it shows. If `null` the tooltip will always be hidden. When given a function, the first argument will be the value and the second will be the index of the slider handle.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dots</td>
|
||||
|
||||
+13
-10
@@ -18,16 +18,19 @@ const handleStyle = {
|
||||
textAlign: 'center',
|
||||
};
|
||||
|
||||
const CustomHandle = props => {
|
||||
const style = Object.assign({ left: `${props.offset}%` }, handleStyle);
|
||||
return (
|
||||
<div style={style}>val: {props.value}</div>
|
||||
);
|
||||
};
|
||||
CustomHandle.propTypes = {
|
||||
value: React.PropTypes.any,
|
||||
offset: React.PropTypes.number,
|
||||
};
|
||||
const CustomHandle = React.createClass({
|
||||
propTypes: {
|
||||
value: React.PropTypes.any,
|
||||
offset: React.PropTypes.number,
|
||||
},
|
||||
render() {
|
||||
const props = this.props;
|
||||
const style = Object.assign({ left: `${props.offset}%` }, handleStyle);
|
||||
return (
|
||||
<div style={style}>val: {props.value}</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
|
||||
+6
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rc-slider",
|
||||
"version": "5.2.1",
|
||||
"version": "5.4.0",
|
||||
"description": "slider ui component for react",
|
||||
"keywords": [
|
||||
"react",
|
||||
@@ -19,10 +19,14 @@
|
||||
},
|
||||
"files": [
|
||||
"assets/*.css",
|
||||
"lib"
|
||||
"lib",
|
||||
"dist"
|
||||
],
|
||||
"licenses": "MIT",
|
||||
"main": "./lib/index.js",
|
||||
"entry": {
|
||||
"rc-slider": ["./assets/index.less", "./src/index.js"]
|
||||
},
|
||||
"style": "./assets/index.css",
|
||||
"config": {
|
||||
"port": 8005
|
||||
|
||||
+9
-7
@@ -10,18 +10,18 @@ export default class Handle extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
showTooltip() {
|
||||
this.setState({
|
||||
isTooltipVisible: true,
|
||||
});
|
||||
}
|
||||
|
||||
hideTooltip() {
|
||||
this.setState({
|
||||
isTooltipVisible: false,
|
||||
});
|
||||
}
|
||||
|
||||
showTooltip() {
|
||||
this.setState({
|
||||
isTooltipVisible: true,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
prefixCls,
|
||||
@@ -34,6 +34,7 @@ export default class Handle extends React.Component {
|
||||
value,
|
||||
dragging,
|
||||
noTip,
|
||||
index,
|
||||
} = this.props;
|
||||
|
||||
const style = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` };
|
||||
@@ -55,7 +56,7 @@ export default class Handle extends React.Component {
|
||||
prefixCls={tooltipPrefixCls || `${prefixCls}-tooltip`}
|
||||
placement="top"
|
||||
visible={isTooltipVisible}
|
||||
overlay={<span>{tipFormatter(value)}</span>}
|
||||
overlay={<span>{tipFormatter(value, index)}</span>}
|
||||
delay={0}
|
||||
transitionName={tipTransitionName}
|
||||
>
|
||||
@@ -76,4 +77,5 @@ Handle.propTypes = {
|
||||
value: React.PropTypes.number,
|
||||
dragging: React.PropTypes.bool,
|
||||
noTip: React.PropTypes.bool,
|
||||
index: React.PropTypes.number,
|
||||
};
|
||||
|
||||
+175
-173
@@ -110,18 +110,24 @@ class Slider extends React.Component {
|
||||
props.onChange(changedValue);
|
||||
}
|
||||
|
||||
onMouseMove(e) {
|
||||
const position = getMousePosition(this.props.vertical, e);
|
||||
this.onMove(e, position - this.dragOffset);
|
||||
onMouseDown(e) {
|
||||
if (e.button !== 0) { return; }
|
||||
|
||||
let position = getMousePosition(this.props.vertical, e);
|
||||
if (!this.isEventFromHandle(e)) {
|
||||
this.dragOffset = 0;
|
||||
} else {
|
||||
const handlePosition = getHandleCenterPosition(this.props.vertical, e.target);
|
||||
this.dragOffset = position - handlePosition;
|
||||
position = handlePosition;
|
||||
}
|
||||
this.onStart(position);
|
||||
this.addDocumentEvents('mouse');
|
||||
pauseEvent(e);
|
||||
}
|
||||
|
||||
onTouchMove(e) {
|
||||
if (isNotTouchEvent(e)) {
|
||||
this.end('touch');
|
||||
return;
|
||||
}
|
||||
|
||||
const position = getTouchPosition(this.props.vertical, e);
|
||||
onMouseMove(e) {
|
||||
const position = getMousePosition(this.props.vertical, e);
|
||||
this.onMove(e, position - this.dragOffset);
|
||||
}
|
||||
|
||||
@@ -154,38 +160,6 @@ class Slider extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
onTouchStart(e) {
|
||||
if (isNotTouchEvent(e)) return;
|
||||
|
||||
let position = getTouchPosition(this.props.vertical, e);
|
||||
if (!this.isEventFromHandle(e)) {
|
||||
this.dragOffset = 0;
|
||||
} else {
|
||||
const handlePosition = getHandleCenterPosition(this.props.vertical, e.target);
|
||||
this.dragOffset = position - handlePosition;
|
||||
position = handlePosition;
|
||||
}
|
||||
this.onStart(position);
|
||||
this.addDocumentEvents('touch');
|
||||
pauseEvent(e);
|
||||
}
|
||||
|
||||
onMouseDown(e) {
|
||||
if (e.button !== 0) { return; }
|
||||
|
||||
let position = getMousePosition(this.props.vertical, e);
|
||||
if (!this.isEventFromHandle(e)) {
|
||||
this.dragOffset = 0;
|
||||
} else {
|
||||
const handlePosition = getHandleCenterPosition(this.props.vertical, e.target);
|
||||
this.dragOffset = position - handlePosition;
|
||||
position = handlePosition;
|
||||
}
|
||||
this.onStart(position);
|
||||
this.addDocumentEvents('mouse');
|
||||
pauseEvent(e);
|
||||
}
|
||||
|
||||
onStart(position) {
|
||||
const props = this.props;
|
||||
props.onBeforeChange(this.getValue());
|
||||
@@ -231,34 +205,30 @@ class Slider extends React.Component {
|
||||
this.onChange({ bounds: nextBounds });
|
||||
}
|
||||
|
||||
getValue() {
|
||||
const { bounds } = this.state;
|
||||
return this.props.range ? bounds : bounds[1];
|
||||
}
|
||||
|
||||
getSliderLength() {
|
||||
const slider = this.refs.slider;
|
||||
if (!slider) {
|
||||
return 0;
|
||||
onTouchMove(e) {
|
||||
if (isNotTouchEvent(e)) {
|
||||
this.end('touch');
|
||||
return;
|
||||
}
|
||||
|
||||
return this.props.vertical ? slider.clientHeight : slider.clientWidth;
|
||||
const position = getTouchPosition(this.props.vertical, e);
|
||||
this.onMove(e, position - this.dragOffset);
|
||||
}
|
||||
|
||||
getSliderStart() {
|
||||
const slider = this.refs.slider;
|
||||
const rect = slider.getBoundingClientRect();
|
||||
onTouchStart(e) {
|
||||
if (isNotTouchEvent(e)) return;
|
||||
|
||||
return this.props.vertical ? rect.top : rect.left;
|
||||
}
|
||||
|
||||
getPrecision(step) {
|
||||
const stepString = step.toString();
|
||||
let precision = 0;
|
||||
if (stepString.indexOf('.') >= 0) {
|
||||
precision = stepString.length - stepString.indexOf('.') - 1;
|
||||
let position = getTouchPosition(this.props.vertical, e);
|
||||
if (!this.isEventFromHandle(e)) {
|
||||
this.dragOffset = 0;
|
||||
} else {
|
||||
const handlePosition = getHandleCenterPosition(this.props.vertical, e.target);
|
||||
this.dragOffset = position - handlePosition;
|
||||
position = handlePosition;
|
||||
}
|
||||
return precision;
|
||||
this.onStart(position);
|
||||
this.addDocumentEvents('touch');
|
||||
pauseEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,6 +252,76 @@ class Slider extends React.Component {
|
||||
return this._getPointsCache.points;
|
||||
}
|
||||
|
||||
getPrecision(step) {
|
||||
const stepString = step.toString();
|
||||
let precision = 0;
|
||||
if (stepString.indexOf('.') >= 0) {
|
||||
precision = stepString.length - stepString.indexOf('.') - 1;
|
||||
}
|
||||
return precision;
|
||||
}
|
||||
|
||||
getSliderLength() {
|
||||
const slider = this.refs.slider;
|
||||
if (!slider) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.props.vertical ? slider.clientHeight : slider.clientWidth;
|
||||
}
|
||||
|
||||
getSliderStart() {
|
||||
const slider = this.refs.slider;
|
||||
const rect = slider.getBoundingClientRect();
|
||||
|
||||
return this.props.vertical ? rect.top : rect.left;
|
||||
}
|
||||
|
||||
getValue() {
|
||||
const { bounds } = this.state;
|
||||
return this.props.range ? bounds : bounds[1];
|
||||
}
|
||||
|
||||
addDocumentEvents(type) {
|
||||
if (type === 'touch') {
|
||||
// just work for chrome iOS Safari and Android Browser
|
||||
this.onTouchMoveListener =
|
||||
addEventListener(document, 'touchmove', this.onTouchMove.bind(this));
|
||||
this.onTouchUpListener =
|
||||
addEventListener(document, 'touchend', this.end.bind(this, 'touch'));
|
||||
} else if (type === 'mouse') {
|
||||
this.onMouseMoveListener =
|
||||
addEventListener(document, 'mousemove', this.onMouseMove.bind(this));
|
||||
this.onMouseUpListener =
|
||||
addEventListener(document, 'mouseup', this.end.bind(this, 'mouse'));
|
||||
}
|
||||
}
|
||||
|
||||
calcOffset(value) {
|
||||
const { min, max } = this.props;
|
||||
const ratio = (value - min) / (max - min);
|
||||
return ratio * 100;
|
||||
}
|
||||
|
||||
calcValue(offset) {
|
||||
const { vertical, min, max } = this.props;
|
||||
const ratio = Math.abs(offset / this.getSliderLength());
|
||||
const value = vertical ? (1 - ratio) * (max - min) + min : ratio * (max - min) + min;
|
||||
return value;
|
||||
}
|
||||
|
||||
calcValueByPos(position) {
|
||||
const pixelOffset = position - this.getSliderStart();
|
||||
const nextValue = this.trimAlignValue(this.calcValue(pixelOffset));
|
||||
return nextValue;
|
||||
}
|
||||
|
||||
end(type) {
|
||||
this.removeEvents(type);
|
||||
this.props.onAfterChange(this.getValue());
|
||||
this.setState({ handle: null });
|
||||
}
|
||||
|
||||
isEventFromHandle(e) {
|
||||
return this.state.bounds.some((x, i) => (
|
||||
this.refs[`handle-${i}`] &&
|
||||
@@ -293,6 +333,74 @@ class Slider extends React.Component {
|
||||
return value < props.min || value > props.max;
|
||||
}
|
||||
|
||||
pushHandle(bounds, handle, direction, amount) {
|
||||
const originalValue = bounds[handle];
|
||||
let currentValue = bounds[handle];
|
||||
while (direction * (currentValue - originalValue) < amount) {
|
||||
if (!this.pushHandleOnePoint(bounds, handle, direction)) {
|
||||
// can't push handle enough to create the needed `amount` gap, so we
|
||||
// revert its position to the original value
|
||||
bounds[handle] = originalValue;
|
||||
return false;
|
||||
}
|
||||
currentValue = bounds[handle];
|
||||
}
|
||||
// the handle was pushed enough to create the needed `amount` gap
|
||||
return true;
|
||||
}
|
||||
|
||||
pushHandleOnePoint(bounds, handle, direction) {
|
||||
const points = this.getPoints();
|
||||
const pointIndex = points.indexOf(bounds[handle]);
|
||||
const nextPointIndex = pointIndex + direction;
|
||||
if (nextPointIndex >= points.length || nextPointIndex < 0) {
|
||||
// reached the minimum or maximum available point, can't push anymore
|
||||
return false;
|
||||
}
|
||||
const nextHandle = handle + direction;
|
||||
const nextValue = points[nextPointIndex];
|
||||
const { pushable: threshold } = this.props;
|
||||
const diffToNext = direction * (bounds[nextHandle] - nextValue);
|
||||
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
|
||||
// couldn't push next handle, so we won't push this one either
|
||||
return false;
|
||||
}
|
||||
// push the handle
|
||||
bounds[handle] = nextValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
pushSurroundingHandles(bounds, handle, originalValue) {
|
||||
const { pushable: threshold } = this.props;
|
||||
const value = bounds[handle];
|
||||
|
||||
let direction = 0;
|
||||
if (bounds[handle + 1] - value < threshold) {
|
||||
direction = +1;
|
||||
} else if (value - bounds[handle - 1] < threshold) {
|
||||
direction = -1;
|
||||
}
|
||||
|
||||
if (direction === 0) { return; }
|
||||
|
||||
const nextHandle = handle + direction;
|
||||
const diffToNext = direction * (bounds[nextHandle] - value);
|
||||
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
|
||||
// revert to original value if pushing is impossible
|
||||
bounds[handle] = originalValue;
|
||||
}
|
||||
}
|
||||
|
||||
removeEvents(type) {
|
||||
if (type === 'touch') {
|
||||
this.onTouchMoveListener.remove();
|
||||
this.onTouchUpListener.remove();
|
||||
} else if (type === 'mouse') {
|
||||
this.onMouseMoveListener.remove();
|
||||
this.onMouseUpListener.remove();
|
||||
}
|
||||
}
|
||||
|
||||
trimAlignValue(v, nextProps) {
|
||||
const state = this.state || {};
|
||||
const { handle, bounds } = state;
|
||||
@@ -326,114 +434,6 @@ class Slider extends React.Component {
|
||||
return step !== null ? parseFloat(closestPoint.toFixed(this.getPrecision(step))) : closestPoint;
|
||||
}
|
||||
|
||||
pushHandleOnePoint(bounds, handle, direction) {
|
||||
const points = this.getPoints();
|
||||
const pointIndex = points.indexOf(bounds[handle]);
|
||||
const nextPointIndex = pointIndex + direction;
|
||||
if (nextPointIndex >= points.length || nextPointIndex < 0) {
|
||||
// reached the minimum or maximum available point, can't push anymore
|
||||
return false;
|
||||
}
|
||||
const nextHandle = handle + direction;
|
||||
const nextValue = points[nextPointIndex];
|
||||
const { pushable: threshold } = this.props;
|
||||
const diffToNext = direction * (bounds[nextHandle] - nextValue);
|
||||
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
|
||||
// couldn't push next handle, so we won't push this one either
|
||||
return false;
|
||||
}
|
||||
// push the handle
|
||||
bounds[handle] = nextValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
pushHandle(bounds, handle, direction, amount) {
|
||||
const originalValue = bounds[handle];
|
||||
let currentValue = bounds[handle];
|
||||
while (direction * (currentValue - originalValue) < amount) {
|
||||
if (!this.pushHandleOnePoint(bounds, handle, direction)) {
|
||||
// can't push handle enough to create the needed `amount` gap, so we
|
||||
// revert its position to the original value
|
||||
bounds[handle] = originalValue;
|
||||
return false;
|
||||
}
|
||||
currentValue = bounds[handle];
|
||||
}
|
||||
// the handle was pushed enough to create the needed `amount` gap
|
||||
return true;
|
||||
}
|
||||
|
||||
pushSurroundingHandles(bounds, handle, originalValue) {
|
||||
const { pushable: threshold } = this.props;
|
||||
const value = bounds[handle];
|
||||
|
||||
let direction = 0;
|
||||
if (bounds[handle + 1] - value < threshold) {
|
||||
direction = +1;
|
||||
} else if (value - bounds[handle - 1] < threshold) {
|
||||
direction = -1;
|
||||
}
|
||||
|
||||
if (direction === 0) { return; }
|
||||
|
||||
const nextHandle = handle + direction;
|
||||
const diffToNext = direction * (bounds[nextHandle] - value);
|
||||
if (!this.pushHandle(bounds, nextHandle, direction, threshold - diffToNext)) {
|
||||
// revert to original value if pushing is impossible
|
||||
bounds[handle] = originalValue;
|
||||
}
|
||||
}
|
||||
|
||||
calcOffset(value) {
|
||||
const { min, max } = this.props;
|
||||
const ratio = (value - min) / (max - min);
|
||||
return ratio * 100;
|
||||
}
|
||||
|
||||
calcValue(offset) {
|
||||
const { vertical, min, max } = this.props;
|
||||
const ratio = Math.abs(offset / this.getSliderLength());
|
||||
const value = vertical ? (1 - ratio) * (max - min) + min : ratio * (max - min) + min;
|
||||
return value;
|
||||
}
|
||||
|
||||
calcValueByPos(position) {
|
||||
const pixelOffset = position - this.getSliderStart();
|
||||
const nextValue = this.trimAlignValue(this.calcValue(pixelOffset));
|
||||
return nextValue;
|
||||
}
|
||||
|
||||
addDocumentEvents(type) {
|
||||
if (type === 'touch') {
|
||||
// just work for chrome iOS Safari and Android Browser
|
||||
this.onTouchMoveListener =
|
||||
addEventListener(document, 'touchmove', this.onTouchMove.bind(this));
|
||||
this.onTouchUpListener =
|
||||
addEventListener(document, 'touchend', this.end.bind(this, 'touch'));
|
||||
} else if (type === 'mouse') {
|
||||
this.onMouseMoveListener =
|
||||
addEventListener(document, 'mousemove', this.onMouseMove.bind(this));
|
||||
this.onMouseUpListener =
|
||||
addEventListener(document, 'mouseup', this.end.bind(this, 'mouse'));
|
||||
}
|
||||
}
|
||||
|
||||
removeEvents(type) {
|
||||
if (type === 'touch') {
|
||||
this.onTouchMoveListener.remove();
|
||||
this.onTouchUpListener.remove();
|
||||
} else if (type === 'mouse') {
|
||||
this.onMouseMoveListener.remove();
|
||||
this.onMouseUpListener.remove();
|
||||
}
|
||||
}
|
||||
|
||||
end(type) {
|
||||
this.removeEvents(type);
|
||||
this.props.onAfterChange(this.getValue());
|
||||
this.setState({ handle: null });
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
handle,
|
||||
@@ -486,6 +486,7 @@ class Slider extends React.Component {
|
||||
value: v,
|
||||
offset: offsets[i],
|
||||
dragging: handle === i,
|
||||
index: i,
|
||||
key: i,
|
||||
ref: `handle-${i}`,
|
||||
}));
|
||||
@@ -508,9 +509,10 @@ class Slider extends React.Component {
|
||||
|
||||
const sliderClassName = classNames({
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-with-marks`]: Object.keys(marks).length,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
[className]: !!className,
|
||||
[`${prefixCls}-vertical`]: this.props.vertical,
|
||||
[className]: !!className,
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user