Closed
Description
Range Slider should support touch events so users are able to interact with that component as expected. Otherwise it feels broken on mobile devices.
This is related with #480, but not the same. I think this one is more important since the expected behaviour of the component is not achieved with this issue.
I've managed to add the events to the method in charge of this (https://github.com/plotly/plotly.js/blob/master/src/components/rangeslider/draw.js#L158) but seems like I need to do two taps for it to work. I suspect that the touchmove
doesn't trigger just after the touchstart
. Like mousemove
and mousedown
does.
My code:
function setupDragElement(rangeSlider, gd, axisOpts, opts) {
var slideBox = rangeSlider.select('rect.' + constants.slideBoxClassName).node(),
grabAreaMin = rangeSlider.select('rect.' + constants.grabAreaMinClassName).node(),
grabAreaMax = rangeSlider.select('rect.' + constants.grabAreaMaxClassName).node();
function mouseDownHandler() {
var event = d3.event,
target = event.target,
startX = event.clientX || event.touches[0].clientX,
offsetX = startX - rangeSlider.node().getBoundingClientRect().left,
minVal = opts.d2p(axisOpts.range[0]),
maxVal = opts.d2p(axisOpts.range[1]);
var dragCover = dragElement.coverSlip();
dragCover.addEventListener('mousemove', mouseMove);
dragCover.addEventListener('touchmove', mouseMove);
dragCover.addEventListener('mouseup', mouseUp);
dragCover.addEventListener('touchend', mouseUp);
function mouseMove(e) {
var clientX = e.clientX || e.touches[0].clientX;
var delta = +clientX - startX;
var pixelMin, pixelMax, cursor;
switch(target) {
case slideBox:
cursor = 'ew-resize';
pixelMin = minVal + delta;
pixelMax = maxVal + delta;
break;
case grabAreaMin:
cursor = 'col-resize';
pixelMin = minVal + delta;
pixelMax = maxVal;
break;
case grabAreaMax:
cursor = 'col-resize';
pixelMin = minVal;
pixelMax = maxVal + delta;
break;
default:
cursor = 'ew-resize';
pixelMin = offsetX;
pixelMax = offsetX + delta;
break;
}
if(pixelMax < pixelMin) {
var tmp = pixelMax;
pixelMax = pixelMin;
pixelMin = tmp;
}
opts._pixelMin = pixelMin;
opts._pixelMax = pixelMax;
setCursor(d3.select(dragCover), cursor);
setDataRange(rangeSlider, gd, axisOpts, opts);
}
function mouseUp() {
dragCover.removeEventListener('mousemove', mouseMove);
dragCover.removeEventListener('mouseup', mouseUp);
dragCover.removeEventListener('touchmove', mouseMove);
dragCover.removeEventListener('touchend', mouseUp);
Lib.removeElement(dragCover);
}
}
rangeSlider.on('mousedown', mouseDownHandler );
rangeSlider.on('touchstart', mouseDownHandler );
}