Comments (15)
This is already some of the most complex and issue-prone code in D3, so I am wary of adding another code path for a subset of browsers.
Reading a little more about passive event listeners, it seems that you can have a passive event listener that cancels scroll by using the touch-action style property. So perhaps we can make them passive after all?
from d3-drag.
@ernest-okot listeners added via drag.on
will accept 3rd argument as you may see in drag.js@L147
The problem is that drag calls selection.on
internally: namely: inside the drag
function.
Until we get a better API for what's there inside drag
function you may be interested in the following patch:
DON'T USE THIS TECHNIQUE. IT'S HERE FOR A REFERENCE. SEE COMMENTS BELOW
const clone = selection.sort();
// Not sure if it's the best way to clone a selection. I found no other.
// Cloning to prevent exposing patched `on` to the rest of the codebase
clone.on = (() => {
const originalSelectionOn = selection.on.bind(selection);
return (name, fn, options = {passive: true}) =>
originalSelectionOn(name, fn, options);
})();
clone.call(
drag()
.on('start', () => {}, {passive: true})
.on('drag', () => {}, {passive: true})
.on('drag', () => {}, {passive: true})
);
This way I got rid of all [Violation] warnings Chrome Canary showed me: both those that I could pass the 3rd argument (drag.on) and those what drag calls internally.
from d3-drag.
Passive listeners are not appropriate for the drag behavior as it must cancel scrolling.
from d3-drag.
yeah, I noticed that, especially on mobile, it broke some things.
@mbostock do all handlers drag
set up needs to be active or just some of them?
from d3-drag.
You can see the table of events in the README. My guess is that the Violation warnings occur when you have a non-passive event listener that does not call event.preventDefault. Actually, it does occur to me that it might be possible to make the mousedown and touchstart event listeners passive, since due to the convoluted way in which these events need to be handled, the default behavior on these events is not prevented even though mousemove and touchmove are subsequently prevented.
from d3-drag.
So, as I understand, you will think about making some of the internally attached handlers passive, but it's not as easy as saying "this one can be passive and that one not".
Then my patch snippet definitely does more harm than good. I'll leave a remark in the original comment in case someone finds it later.
from d3-drag.
It seems that the Violation appears in the touchstart and touchmove event listeners in Chrome on macOS, even though those event listeners are never invoked (because it’s not a touch device). That seems unfortunate, since it implies that you get a warning even if your event listeners are necessarily non-passive. It might be possible to make the touchstart listener passive, but it’s not possible to make touchmove passive as we need to call event.preventDefault.
Also, per #9, I’d rather always call event.preventDefault. It’s just I can’t because it breaks capturing of mouseup outside the window and it breaks click emulation on touch devices.
from d3-drag.
Thanks for the briefing
from d3-drag.
This might be fixable with Pointer Events (#25) but browser support is still around 60% (behind a flag Firefox, and missing from Safari and iOS).
from d3-drag.
Have you already considered using pointer events when they're available with a fallback to mouse events? I'm just thinking out loud, I'm not aware of if it's worth maintaining that or how complex may it become
from d3-drag.
Too bad it's again Safari that does not respect that
from d3-drag.
Okay. I think I have a good fix for the warning: don’t register touch event listeners on devices that don’t support touch.
from d3-drag.
What about devices like MS Surface which may support touch in general but user has other options?
generally you will have 'ontouchstart' in window === true
on Surface but it's not certain that the user will ever use touch. The current mean of interaction should also be detected (more or less like this):
let currentMeanOfInteractionIsTouch = false;
window.addEventListener('touchstart', () => {
currentMeanOfInteractionIsTouch = true;
// attach other touch event listeners
}, {passive: true})
window.addEventListener('mousedown', () => {
currentMeanOfInteractionIsTouch = false;
// remove touch event listeners but the one above, attach mouse
}, {passive: true})
I just can't tell up front if attaching events on demand won't be either too late or too expensive. How do you think?
from d3-drag.
@jrencz On convertible devices like the Surface you could also try to detect whether it is in tablet mode, e.g. see the discussion at https://stackoverflow.com/questions/32493093, but neither the solutions from there nor your solution belong inside d3 IMHO since it's too use-case specific.
On a side note, I came across this and related bug tracker entries while looking for solutions for issues I was having with pan and drag-drop with d3 in Microsoft Edge and IE11 even in demos from @mbostock. There I learned touch-action
with which I was able to solve the problems by simply disallowing any touch action except for pinch-zoom
inside the SVG, apparently the preventDefault
method isn't working in these browsers.
from d3-drag.
@Herst I do own Surface and I barely use tablet mode. Yet I tend to touch the screen a lot in desktop mode. It serves a purpose of lightweight task home laptop, not a tablet at all in my household. I'd bet I'm not alone in this mode of usage.
So detecting the mode (btw: how can it be done in JS?) is not the best choice IMO
from d3-drag.
Related Issues (20)
- Possible typo in README HOT 2
- What are the perposes of functions yesdrag and nodrag?
- Drag event on Chrome 72 HOT 3
- d3 mouseup event not firing HOT 1
- Drag Event Issue on Windows Chrome 74, related to solution for #47 HOT 1
- The default filter should return false if event.ctrlKey. HOT 5
- drag start event is don't send when Ctrl-key is press HOT 1
- drag.on("init") ? HOT 7
- Click event not firing if drag enables with simulation HOT 1
- Non-cancelable event HOT 3
- remove drag.container? HOT 1
- Use native events (*element*.dispatchEvent) instead of d3-dispatch? HOT 1
- remove dragEvent.on?
- d3.event is not available in version 6.1.1 HOT 1
- DragEvent missing event.currentTarget for arrow function node selection HOT 1
- Make event listeners non-passive. HOT 2
- d3.drag() causes error in testing mousedown event via jsdom HOT 4
- d3.pointer() could use event.touches[0] HOT 2
- Add event.currentTarget
- Support d3.drag in testing environments
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from d3-drag.