diff --git a/assets/index.less b/assets/index.less index e78ae26a6..b5b24df52 100644 --- a/assets/index.less +++ b/assets/index.less @@ -27,7 +27,6 @@ padding: 5px 0; width: 100%; border-radius: @border-radius-base; - touch-action: none; .borderBox(); &-rail { @@ -58,7 +57,6 @@ border-radius: 50%; border: solid 2px tint(@primary-color, 50%); background-color: #fff; - touch-action: pan-x; &:hover { border-color: tint(@primary-color, 20%); @@ -143,6 +141,14 @@ cursor: not-allowed!important; } } + + &-dragging { + touch-action: none; + + .@{prefixClass}-handle { + touch-action: pan-x; + } + } } .@{prefixClass}-vertical { @@ -165,7 +171,6 @@ &-handle { margin-left: -5px; margin-bottom: -7px; - touch-action: pan-y; } &-mark { diff --git a/src/common/createSlider.jsx b/src/common/createSlider.jsx index 217d4ceb5..161ceff44 100644 --- a/src/common/createSlider.jsx +++ b/src/common/createSlider.jsx @@ -114,18 +114,18 @@ export default function createSlider(Component) { onTouchStart = (e) => { if (utils.isNotTouchEvent(e)) return; - const isVertical = this.props.vertical; - let position = utils.getTouchPosition(isVertical, e); - if (!utils.isEventFromHandle(e, this.handlesRefs)) { - this.dragOffset = 0; - } else { - const handlePosition = utils.getHandleCenterPosition(isVertical, e.target); - this.dragOffset = position - handlePosition; - position = handlePosition; - } - this.onStart(position); + + this.previousTouches = e.touches; + this.isDragging = true; + this.isFirstTouchMoveDone = false; this.addDocumentTouchEvents(); - utils.pauseEvent(e); + } + + onTouchEnd = (e) => { + if (utils.isNotTouchEvent(e)) return; + + this.previousTouches = null; + this.isDragging = false; } onFocus = (e) => { @@ -193,8 +193,35 @@ export default function createSlider(Component) { return; } + if (!this.isFirstTouchMoveDone) { + if (!utils.isRightDirection(e.touches, this.previousTouches, this.props.vertical)) { + this.onEnd(); + return; + } + + this.onFirstTouchMove(e); + this.previousTouches = e.touches; + this.isFirstTouchMoveDone = true; + return; + } + const position = utils.getTouchPosition(this.props.vertical, e); this.onMove(e, position - this.dragOffset); + this.previousTouches = e.touches; + } + + onFirstTouchMove = (e) => { + const isVertical = this.props.vertical; + let position = utils.getTouchPosition(isVertical, e); + if (!utils.isEventFromHandle(e, this.handlesRefs)) { + this.dragOffset = 0; + } else { + const handlePosition = utils.getHandleCenterPosition(isVertical, e.target); + this.dragOffset = position - handlePosition; + position = handlePosition; + } + this.onStart(position); + utils.pauseEvent(e); } onKeyDown = (e) => { @@ -284,6 +311,7 @@ export default function createSlider(Component) { [`${prefixCls}-with-marks`]: Object.keys(marks).length, [`${prefixCls}-disabled`]: disabled, [`${prefixCls}-vertical`]: vertical, + [`${prefixCls}-dragging`]: this.isDragging, [className]: className, }); return ( @@ -291,6 +319,7 @@ export default function createSlider(Component) { ref={this.saveSlider} className={sliderClassName} onTouchStart={disabled ? noop : this.onTouchStart} + onTouchEnd={disabled ? noop : this.onTouchEnd} onMouseDown={disabled ? noop : this.onMouseDown} onKeyDown={disabled ? noop : this.onKeyDown} onFocus={disabled ? noop : this.onFocus} diff --git a/src/createSliderWithTooltip.jsx b/src/createSliderWithTooltip.jsx index e0d90c53f..8d0fa239c 100644 --- a/src/createSliderWithTooltip.jsx +++ b/src/createSliderWithTooltip.jsx @@ -43,10 +43,10 @@ export default function createSliderWithTooltip(Component) { visible = visible || false, ...restTooltipProps, } = tipProps; - + let handleStyleWithIndex = handleStyle[0]; if (handleStyle[index]) { - handleStyleWithIndex = handleStyle[index]; + handleStyleWithIndex = handleStyle[index]; } return ( diff --git a/src/utils.js b/src/utils.js index 07211cc7a..7368e8512 100644 --- a/src/utils.js +++ b/src/utils.js @@ -90,3 +90,43 @@ export function getKeyboardValueMutator(e) { default: return undefined; } } + +// http://hammerjs.github.io/api/#directions +export const DIRECTION_NONE = 1; // 00001 +export const DIRECTION_LEFT = 2; // 00010 +export const DIRECTION_RIGHT = 4; // 00100 +export const DIRECTION_UP = 8; // 01000 +export const DIRECTION_DOWN = 16; // 10000 + +/** + * @private + * get the direction between two points + * @param {Number} x + * @param {Number} y + * @return {Number} direction + */ +export function getDirection(x, y) { + if (x === y) { + return DIRECTION_NONE; + } + if (Math.abs(x) >= Math.abs(y)) { + return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; + } + return y < 0 ? DIRECTION_UP : DIRECTION_DOWN; +} + +export function getTouchDirection(startTouches, touches) { + const { clientX: x1, clientY: y1 } = startTouches[0]; + const { clientX: x2, clientY: y2 } = touches[0]; + const deltaX = x2 - x1; + const deltaY = y2 - y1; + return getDirection(deltaX, deltaY); +} + +export function isRightDirection(startTouches, touches, vertical) { + const direction = getTouchDirection(startTouches, touches); + if (vertical) { + return direction === DIRECTION_UP || direction === DIRECTION_DOWN; + } + return direction === DIRECTION_LEFT || direction === DIRECTION_RIGHT; +}