+
Slider with marks, `step=null`
+
+
+
+
Slider with marks and steps
+
+
+
+
Slider with marks, `included=false`
+
+
+
+
Slider with marks and steps, `included=false`
+
+
+
+
Range with marks
+
+
+
+
Range with marks and steps
+
+
+
+
+ , document.getElementById('__react-content'));
diff --git a/examples/v-range.html b/examples/v-range.html
new file mode 100644
index 0000000..e69de29
diff --git a/examples/v-range.js b/examples/v-range.js
new file mode 100644
index 0000000..5ecf9be
--- /dev/null
+++ b/examples/v-range.js
@@ -0,0 +1,117 @@
+/* eslint react/no-multi-comp: 0 */
+require('rc-slider/assets/index.less');
+
+const React = require('react');
+const ReactDOM = require('react-dom');
+const Slider = require('rc-slider');
+
+const style = {height: 400, marginBottom: 50, marginLeft: 50};
+
+function log(value) {
+ console.log(value);
+}
+
+const CustomizedRange = React.createClass({
+ getInitialState: function() {
+ return {
+ lowerBound: 20,
+ upperBound: 40,
+ value: [20, 40],
+ };
+ },
+ onLowerBoundChange: function(e) {
+ this.setState({ lowerBound: +e.target.value });
+ },
+ onUpperBoundChange: function(e) {
+ this.setState({ upperBound: +e.target.value });
+ },
+ onSliderChange: function(value) {
+ log(value);
+ this.setState({
+ value: value,
+ });
+ },
+ handleApply: function() {
+ const { lowerBound, upperBound } = this.state;
+ this.setState({ value: [lowerBound, upperBound]});
+ },
+ render: function() {
+ return (
+ {
+const Marks = ({className, vertical, marks, included, upperBound, lowerBound, max, min}) => {
const marksKeys = Object.keys(marks);
const marksCount = marksKeys.length;
const unit = 100 / (marksCount - 1);
@@ -16,11 +16,19 @@ const Marks = ({className, marks, included, upperBound, lowerBound, max, min}) =
[className + '-text-active']: isActived,
});
- const style = {
+ const bottomStyle = {
+ // height: markWidth + '%',
+ marginBottom: '-200' + '%',
+ bottom: (point - min) / range * 100 + '%',
+ };
+
+ const leftStyle = {
width: markWidth + '%',
marginLeft: -markWidth / 2 + '%',
+ left: (point - min) / range * 100 + '%',
};
- style.left = (point - min) / range * 100 + '%';
+
+ const style = vertical ? bottomStyle : leftStyle;
const markPoint = marks[point];
const markPointIsObject = typeof markPoint === 'object' &&
diff --git a/src/Slider.jsx b/src/Slider.jsx
index e2aa6bb..991fc7b 100644
--- a/src/Slider.jsx
+++ b/src/Slider.jsx
@@ -13,12 +13,12 @@ function isNotTouchEvent(e) {
return e.touches.length > 1 || (e.type.toLowerCase() === 'touchend' && e.touches.length > 0);
}
-function getTouchPosition(e) {
- return e.touches[0].pageX;
+function getTouchPosition(vertical, e) {
+ return vertical ? e.touches[0].clientY : e.touches[0].pageX;
}
-function getMousePosition(e) {
- return e.pageX;
+function getMousePosition(vertical, e) {
+ return vertical ? e.clientY : e.pageX;
}
function pauseEvent(e) {
@@ -113,7 +113,7 @@ class Slider extends React.Component {
}
onMouseMove(e) {
- const position = getMousePosition(e);
+ const position = getMousePosition(this.props.vertical, e);
this.onMove(e, position);
}
@@ -123,7 +123,7 @@ class Slider extends React.Component {
return;
}
- const position = getTouchPosition(e);
+ const position = getTouchPosition(this.props.vertical, e);
this.onMove(e, position);
}
@@ -132,7 +132,8 @@ class Slider extends React.Component {
const props = this.props;
const state = this.state;
- const diffPosition = position - this.startPosition;
+ let diffPosition = position - this.startPosition;
+ diffPosition = this.props.vertical ? -diffPosition : diffPosition;
const diffValue = diffPosition / this.getSliderLength() * (props.max - props.min);
const value = this.trimAlignValue(this.startValue + diffValue);
@@ -164,14 +165,14 @@ class Slider extends React.Component {
onTouchStart(e) {
if (isNotTouchEvent(e)) return;
- const position = getTouchPosition(e);
+ const position = getTouchPosition(this.props.vertical, e);
this.onStart(position);
this.addDocumentEvents('touch');
pauseEvent(e);
}
onMouseDown(e) {
- const position = getMousePosition(e);
+ const position = getMousePosition(this.props.vertical, e);
this.onStart(position);
this.addDocumentEvents('mouse');
pauseEvent(e);
@@ -229,14 +230,14 @@ class Slider extends React.Component {
return 0;
}
- return slider.clientWidth;
+ return this.props.vertical ? slider.clientHeight : slider.clientWidth;
}
getSliderStart() {
const slider = this.refs.slider;
const rect = slider.getBoundingClientRect();
- return rect.left;
+ return this.props.vertical ? rect.top : rect.left;
}
getPrecision() {
@@ -291,9 +292,10 @@ class Slider extends React.Component {
}
calcValue(offset) {
- const {min, max} = this.props;
- const ratio = offset / this.getSliderLength();
- return ratio * (max - min) + min;
+ 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) {
@@ -331,7 +333,7 @@ class Slider extends React.Component {
render() {
const {handle, upperBound, lowerBound} = this.state;
- const {className, prefixCls, disabled, dots, included, range, step,
+ const {className, prefixCls, disabled, vertical, dots, included, range, step,
marks, max, min, tipTransitionName, tipFormatter, children} = this.props;
const upperOffset = this.calcOffset(upperBound);
@@ -342,19 +344,20 @@ class Slider extends React.Component {
const upper = (
);
+ vertical = {vertical} offset={upperOffset} value={upperBound} dragging={handle === 'upperBound'}/>);
let lower = null;
if (range) {
lower = (
);
+ vertical = {vertical} offset={lowerOffset} value={lowerBound} dragging={handle === 'lowerBound'}/>);
}
const sliderClassName = classNames({
[prefixCls]: true,
[prefixCls + '-disabled']: disabled,
[className]: !!className,
+ ['rc-slider-vertical']: this.props.vertical,
});
const isIncluded = included || range;
return (
@@ -363,12 +366,12 @@ class Slider extends React.Component {
onMouseDown={disabled ? noop : this.onMouseDown.bind(this)}>
{upper}
{lower}
-
-
-
{children}
@@ -402,6 +405,7 @@ Slider.propTypes = {
tipFormatter: React.PropTypes.func,
dots: React.PropTypes.bool,
range: React.PropTypes.bool,
+ vertical: React.PropTypes.bool,
allowCross: React.PropTypes.bool,
};
@@ -421,6 +425,7 @@ Slider.defaultProps = {
disabled: false,
dots: false,
range: false,
+ vertical: false,
allowCross: true,
};
diff --git a/src/Steps.jsx b/src/Steps.jsx
index e3e969e..5f33e7c 100644
--- a/src/Steps.jsx
+++ b/src/Steps.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import classNames from 'classnames';
-function calcPoints(marks, dots, step, min, max) {
+function calcPoints(vertical, marks, dots, step, min, max) {
const points = Object.keys(marks).map(parseFloat);
if (dots) {
for (let i = min; i <= max; i = i + step) {
@@ -12,12 +12,12 @@ function calcPoints(marks, dots, step, min, max) {
return points;
}
-const Steps = ({prefixCls, marks, dots, step, included,
+const Steps = ({prefixCls, vertical, marks, dots, step, included,
lowerBound, upperBound, max, min}) => {
const range = max - min;
- const elements = calcPoints(marks, dots, step, min, max).map((point) => {
- const offset = (point - min) / range * 100 + '%';
- const style = { left: offset };
+ const elements = calcPoints(vertical, marks, dots, step, min, max).map((point) => {
+ const offset = Math.abs(point - min) / range * 100 + '%';
+ const style = vertical ? { bottom: offset } : { left: offset };
const isActived = (!included && point === upperBound) ||
(included && point <= upperBound && point >= lowerBound);
diff --git a/src/Track.jsx b/src/Track.jsx
index 70df9ed..bcecba2 100644
--- a/src/Track.jsx
+++ b/src/Track.jsx
@@ -1,11 +1,16 @@
import React from 'react';
-const Track = ({className, included, offset, length}) => {
+const Track = ({className, included, vertical, offset, length}) => {
const style = {
- left: offset + '%',
- width: length + '%',
visibility: included ? 'visible' : 'hidden',
};
+ if (vertical) {
+ style.bottom = offset + '%';
+ style.height = length + '%';
+ } else {
+ style.left = offset + '%';
+ style.width = length + '%';
+ }
return ;
};
diff --git a/tests/index.spec.js b/tests/index.spec.js
index ca2bd0d..e654238 100644
--- a/tests/index.spec.js
+++ b/tests/index.spec.js
@@ -6,7 +6,7 @@ const Slider = require('..');
require('../assets/index.less');
-describe('rc-slider', function() {
+describe('rc-slider', function test() {
this.timeout(5000);
const div = document.createElement('div');
document.body.appendChild(div);
@@ -140,4 +140,9 @@ describe('rc-slider', function() {
expect(range.state.upperBound).to.be(90);
ReactDOM.unmountComponentAtNode(div);
});
+
+ it('should render a vertical slider, when `vertical` is true', () => {
+ const slider = ReactDOM.render(, div);
+ expect(ReactTestUtils.scryRenderedDOMComponentsWithClass(slider, 'rc-slider-vertical').length).to.be(1);
+ });
});