Skip to content
This repository has been archived by the owner on Oct 9, 2019. It is now read-only.

JS Interop: Direct Access to "draw()"? #25

Closed
felixguendling opened this issue Jun 12, 2016 · 5 comments
Closed

JS Interop: Direct Access to "draw()"? #25

felixguendling opened this issue Jun 12, 2016 · 5 comments

Comments

@felixguendling
Copy link

felixguendling commented Jun 12, 2016

I'm currently experimenting using elm-webgl to power a canvas on a Leaflet.js map to render geo data. Basically, this is working great! I think Elm could be a good fit to render big amounts of live geo data.

Unfortunately, the JS Ports feature of Elm seems to be asynchronous which leads to a laggy view. I've created an example to show the behavior: https://github.com/felixguendling/elm-map/tree/master

The rendering works fine, but when you drag/move the map, the canvas contents get displayed at the wrong position for perhaps a few milliseconds. I assume this glitch originates from the ports not being synchronous. There are some plain JS examples that do the same with the slight difference, that the canvas update happens at the same time as the CSS update of the map.

Problem in the code (https://github.com/felixguendling/elm-map/blob/master/index.html):

app.ports.mapUpdate.send

and

var pos = this._map.containerPointToLayerPoint([0, 0]);
L.DomUtil.setPosition(this._el, pos);

are not synchronized.

So, my question is: is there a way to instantly render the changes or are there some kind of "synchronous ports" in Elm? Or is there a totally different solution to this problem?

Edit: The model needs to be updated before the synchronous redraw.

@w0rm
Copy link
Member

w0rm commented Jun 14, 2016

@felixguendling why do you want to move the canvas element, and not the triangle within it? You could've sent the offset to webgl and use it to offset the triangle.

@w0rm
Copy link
Member

w0rm commented Jun 14, 2016

@felixguendling, sorry. I see why you need it now, it is moved with the main map and you have to reposition it with the opposite offset.

@felixguendling
Copy link
Author

felixguendling commented Jun 14, 2016

@w0rm thank you for looking into the problem.

Yes. That's the approach other implementations use, too. This way, I don't have to use the "move" callback commented out in the file: https://github.com/felixguendling/elm-map/blob/master/index.html#L24

If I use the "move" callback (and position the canvas outside, not as child DOM of the map), another undesired "effect" appears: the constant rerender is not exactly synchronous with the drag movement of the user. Thus, the triangle is not at the same geographical location which looks weird. Furthermore, the system load increases significantly when dragging the map around (laptop fan makes noise).

I think this is a problem with Elm Ports being asynchronous in general, making real-time JS interop hard. But perhaps there is a way to solve this specific problem without touching the Elm compiler?

Edit: I thought about implementing a simple tile-based map in Elm (which would result in synchronous updates!). But I think that's not an easy problem. So using an existing mature library like Leaflet was my first approach.

@nphollon
Copy link
Collaborator

This seems like a great topic to bring up on the elm-dev mailing list.

As for finding a work-around within elm-webgl, I don't see a good way of doing it. You'd have to decouple from Elm's VDOM render loop somehow, right?

@felixguendling
Copy link
Author

Thanks for the hint. I opened a discussion:
https://groups.google.com/forum/#!topic/elm-dev/lAEnpHQzS5c

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants