-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Closed
Labels
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 );
}
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
etpinard commentedon Oct 28, 2016
Thanks very much for writing in
I suspect our range sliders will update painfully slowly on mobile, but hey, if you want to add this in. PR away 🚀
cristiantx commentedon Oct 31, 2016
@etpinard On a not too related matter, I noticed that performance issue on mobile. I was wondering if the chart could update on
touchend
event instead of live. That would make the performance issue much less noticeable (I was taking a look to other libraries and seems like Highcharts for instance, do this).But I've noticed that rangeslider draw update is pretty much bounded with the actual chart. Can you point me out (if you know) if there is something I can look into to try to make this change in behavior.
What I want, drag/resize range slider and update the chart only on
touchend
ormouseup
, probably I will be making this behavior an option.etpinard commentedon Nov 1, 2016
That sounds like a good idea.
I'm not sure what you mean here. Could you try to clarify?
cristiantx commentedon Nov 2, 2016
@etpinard Sure, on
mousemove
event, the methodsetDataRange
is called, which is in charge of updating the chart to the new range. Code hereAnd this method calls this:
Which seems to relayout everything (slider range and actual chart). I couldn't find a way to isolate this two different draws.
So, the question in other words, is there a way to update live just the slider range? Or an idea/clue on where to start looking.
etpinard commentedon Nov 2, 2016
That's correct.
I think the best way to solve this problem would be to make the
ontouchmove
handler not callsetDataRange
and instead callsetPixelRange
which will take care of updating the handle positions. ThensetDataRange
could be called inside aontouchend
handler.cristiantx commentedon Nov 2, 2016
Thanks @etpinard! I will give it a try
JasDev42 commentedon Mar 7, 2018
Hey people,
I used the fix provided by @cristiantx but was facing the issue he mentioned.
So fix for
touchmove
andtouchend
is to usethis
instead ofdragCover
Here is the updated code:
Berezhnyk commentedon Nov 1, 2019
Any updates?
forforeach commentedon May 24, 2020
Any news on this?
Add Touch Support to RangeSlider plotly#1098
Merge pull request #5025 from priyanomi/range-slider-touch-integration
archmoj commentedon Sep 9, 2020
Closed via #5025.