Custom canvas drawing in MapView v4.10

2461
7
Jump to solution
12-19-2018 01:40 PM
NickCameron2
New Contributor III

I'm currently using one custom layer and am building another that draws on a canvas manually in a map view.

The existing one is here: https://github.com/nickcam/AnimatedEnvironmentLayer

In v4.9 at a high level the following steps would allow this to happen.

- Subclass a layer

- Create a new canvas element and append it to the container element of the layer.

- If a feature layer swap the context of the layer with one created from the new canvas. 

In 4.10 with the drawing occurring all in one webgl context (which is great by the way!), I can't inject a new canvas to essentially replace the svg or the existing canvas for an individual layer.

I've tried using the BaseLayerView2D and can get part of the way, but each render() call seems to clear the context and I'm looking to maintain drawing across frames as in the layer linked above. I don't have a simple example of this at the moment but can put one together if it would help.

Are there any examples or patterns that could help with this? Perhaps a custom draw BaseLayerView in a future release?

0 Kudos
1 Solution

Accepted Solutions
YannCabon
Esri Contributor

I see,

The layerview is probably clearing the trail at every frame when it sets the canvas size which clears the previous content. What you can do is create your own canvas, draw the data in it, then use drawImage(canvas) on the context of the layerview.

View solution in original post

0 Kudos
7 Replies
YannCabon
Esri Contributor

Hi Nick,

I checked out the project locally, pretty cool

To integrate properly in 2D you will have to implement a custom layerview by extending the BaseLayerView2D.

See https://developers.arcgis.com/javascript/latest/api-reference/esri-views-2d-layers-BaseLayerView2D.h...

Basically you implement the base class and its render function. This function is called at each frame with the current view state as well as a canvas' ContextRendering2D that you can use to draw. Then we compose the canvas with the rest of the webgl content.

The base class also gives you information about tiles if you want this kind of info.

Cheers

Yann

0 Kudos
NickCameron2
New Contributor III

Hi Yann,

Yeah I've been trying to use BaseLayerView2D, but just can't get it quite right. It's working ok without the fade out of the existing drawing, so essentially an object will move around the canvas but without the trail. I can't stop it from clearing the context on each render call. Even with this happening, there is some flicker when zoomed out though. 

I'm using render() and requestRender() to form the animation loop, so something is happening in that pipeline that won't maintain the previously drawn frame into the current frame...or more likely I'm just doing it wrong .

I'm guessing this has to do with the copying of the 2d context canvas to the webgl context for the actual drawing?? Have overridden the BaseLayerView2D containers doRender() method and played around in it a little to try and get around this, but no joy so far. Didn't want to go too far down the hole of overriding api code though.

I've been trying all of this on a new layer that which will behave very similar to the existing one, but will be driven by feature polygons and not just GRIB data so it's more generic. If I put the progress on github, whenever you get a chance would you be able to take a look?

Thanks,

Nick

0 Kudos
YannCabon
Esri Contributor

I see,

The layerview is probably clearing the trail at every frame when it sets the canvas size which clears the previous content. What you can do is create your own canvas, draw the data in it, then use drawImage(canvas) on the context of the layerview.

0 Kudos
NickCameron2
New Contributor III

Ok cool. Will give that a crack.

I had originally tried creating and drawing on a new canvas as that worked prior to 4.10, and it draws fine using my own animation loop, but it was then outside the flow of the general map and it's layers. As in setting properties on the layer wouldn't affect the drawing, ie: opacity, visible, ordering, so basically broke the api to the layer. Could manually handle these except for the ordering I imagine though.

Anyway, will give that another go - thanks for your help!

0 Kudos
NickCameron2
New Contributor III

Ohhh...I think i misunderstood, now I get what you mean. Draw on the custom canvas, separate animation loop or whatever, but don't display it I guess, then draw that canvas contents to the internal api context as part of the render pipeline loop. That would keep the drawn layer in the normal flow. Once again, thanks!

0 Kudos
NickCameron2
New Contributor III

Sorry for the spam comments...but just tried that out and it worked a treat!

0 Kudos
YannCabon
Esri Contributor

no worries! happy that you got that working!

0 Kudos