-
Notifications
You must be signed in to change notification settings - Fork 205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New input event handling #113
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for opening a PR, it looks like most of the functionality we talked about is in there!
This is not a proper review. I have mostly tried to read the code and attempt to understand the design, and made some comments as I went along. They are mostly stylistic at this point.
To do a proper review, what I most need to understand is what the public API will look like (is it just the addEvents
function that is public, and are all the other classes internal?).
Also if there was a single line of comment, or even better proper JSDoc, at least on the constructors and public methods of all classes, that would really help clarify the intended design.
@@ -0,0 +1,60 @@ | |||
/* global console */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filenames. Convention in luma.gl is to use underscore_case
for filenames, matching names of classes that are in PascalCase
.
So this would be event-manager.js
@@ -0,0 +1,15 @@ | |||
import autobind from 'autobind-decorator'; | |||
|
|||
export default class ElementRelativePositionTransformer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless there is more coming, maybe a creating a separate class and file is overkill here? A utility function transformRelativeElementPosition(element, eventPosition)
would seem more lightweight and appropriate, and such a function could be placed in the same file as a couple of other utilities.
@@ -0,0 +1,19 @@ | |||
const modifierEventKeyMap = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this could go in a utils.js
file together with ElementRelativePositionTransformer.js
?
Shift: 'shiftKey' | ||
}; | ||
|
||
export default function createGetModifierState(rawEvent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to do this without a closure? Not a huge thing, but it seems like an ES5 idiom. Even the createGetModifierState
name is a good indication, combining create
and get
in the same function makes it sound more complex than it is.
import TouchEventManager from './TouchEventManager'; | ||
|
||
export default function addEvents(element, userHandlers, options) { | ||
const tranformPosition = (new ElementRelativePositionTransformer(element)).fromViewportRelative; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parenthesis around the new
expression should not be needed here.
/* global console */ | ||
|
||
export default class EventManager { | ||
constructor(nextHandlers) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name here throws me off, i.e. the next
in nextHandlers
? Is the idea that the app can have multiple handlers for the same event? Why not just call the parameter handlers
?
Some JSDoc would be invaluable.
this._nextHandlers = nextHandlers; | ||
} | ||
|
||
attach(element) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the idea here is that the same handler can be added to multiple elements?
Something to consider: Is that worth the additional complexity in the API? As opposed to just creating new handlers.
|
||
attach(element) { | ||
for (const eventType of this.constructor.handledRawEventTypes) { | ||
element.addEventListener(eventType, this[eventType]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thought: If we add handlers, should we also have a way of removing them? Maybe a TODO for the design?
}; | ||
} | ||
|
||
getMiddlewareHandlers() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming here:
- What do we mean with 'middleware' in this context?
- No underscore - is this a public function? If so when should it be called?
- luma classes usually have public methods first, followed by private (underscore) methods.
Again JSDoc would come to the rescue here.
Among the things you list, I'd prioritize those two points, as they will accelerate getting this merged. Others look like nice incremental improvements. The more docs there are, the more straightforward it will be to review this, e.g:
|
@tehwalris I have created a new branch, 'events', off the latest master - rebase your PR towards that branch and I'll merge. It would allow us to test what you are doing, propose some changes and help you out with some of the remaining work. One thing we would like to build are some simple event controllers on top of the new event handling, so it would be good to get it in place soon. |
@ibgreen I've rebased my PR, however merging this directly is a breaking change. The new event framework is currently in the place where the legacy one was and there is no back-compatibility layer implemented yet. What do you mean by "event controllers" that you want to implement? |
@tehwalris- I'm thinking about packaging up some common interaction patterns (like panning/tilting a plane, or rotating around a center point) into simple classes that registers events and keeps updating a view matrix when events are fired. This could be used to package up the current deck.gl event handling or create something like the event THREE.js orbit controls This would allow a luma app to add a basic interactivity with a single line of code. |
We could move your new module to We'd thus keep the old event handling as default for now while making it possible to play with your new system e.g. in deck.gl. What do you think? |
I think For the event controllers you are making, they would be implemented extending For further updates to the event code, I should open another PR, correct? |
Sounds good. You can open a new PR now to move the code over to experimental, that will make it easier to review your changes. About the controllers - I expect they might need touch events from several sources (e.g. both mouse and keyboard) so subclassing from one of these controllers might be too restrictive? As you can probably see, I am still not fully up to speed on your vision here - e.g. if applications are expected to use those controllers directly or mostly use |
@ibgreen I expected applications to only use Different events are handled by So for example a mouse down event goes through the following:
Then there are For a touch down event, a possible flow is:
|
@tehwalris
Sounds good. I wasn't sure about the priority for you, since I think this all originated from a bug you reported in deck.gl. I totally appreciate that this is something you are doing for fun. The pace is up to you. Contributions are always welcome and I am mainly trying to make sure you are unblocked and give you clear guidance on how to get this merged into master. |
This is the new event handling system that I'm creating, with the goal to replace the legacy code in luma.gl which is currently handling events, following issue #112. This is not a full PR yet, just a request for review. The following points need to be addressed before this is ready:
There is one known issue in this code, which I have not found a way to fix. In Chrome on Android, the address bar scrolls off screen, together with the page scroll. This means that the viewport size changes during movement. It seems that clientX/Y on touch events are still reported relative to the original viewport as the user is dragging to hide this address bar. This means that the user sees the pointer in a slightly wrong position if they are performing a touch which is also scrolling the page and this address bar out of view. After releasing their touch, so that the address bar "confirms" it's change to show/hide, everything works correctly again. You can use the basic "touch" test page to see this issue.
I'd love to get some feedback on my work so far, as well as any ideas to fix that issue.