Skip to content
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

Vue lacks idiomatic way to draw into canvas #10426

Closed
tim-janik opened this issue Aug 23, 2019 · 2 comments
Closed

Vue lacks idiomatic way to draw into canvas #10426

tim-janik opened this issue Aug 23, 2019 · 2 comments

Comments

@tim-janik
Copy link

What problem does this feature solve?

Searching the web for ways to paint into a canvas with Vue yields different hacks people had to come up with to marry the two. Some examples: http://simblob.blogspot.com/2018/03/using-vue-with-canvas.html https://stackoverflow.com/questions/44971399/how-can-vuejs-canvas-context-be-linked-together

There are two approaches possible:

a) Drawing into the < canvas/> element occurs synchronously from within the VNode render() function, e.g. via using a computed property or simply inserting {{render_canvas()}} in a template.

b) Drawing into the < canvas/> element occurs outside the VNode render() function, e.g. from within updated(), setTimeout() or sometimes asynchronously due to await data_needed_during_draw().

They all suffer from at least one problem however:

  1. Drawing code that is executed from within render() is very brittle. First, a guard is needed to avoid drawing upon the first render() call, because $el/$refs have not been created. Second, drawing via $el/$refs always draws into the canvas created by the last render() call, so if Vue's patch phase exchanges the DOM elements, the drawings are lost. Third, even just width / height property updates during the patch phase will cause HTML5 < canvas/> objects to clear themselves, so the drawing results are also lost.

  2. Drawing outside of render(), in particular during updated() used to work properly (up to early Vue 2.5 IIRC), because at this point the $el/$refs are not stale and the DOM attributes have been assigned. However, since the "fix" to Pitfalls of Vue dependency detection may cause redundant dependencies #7573 was released, reactive property uses during updated() are ignored, which means people have to go back to manual tracking of all possible dependencies involved in drawing and then update a :key or call $forceUpdate() etc.

Given the way render() patch are a fundamental part of the Vue core, I have a hard time seeing how a {{render_canvas()}} template call could be guaranteed to have a readily setup context with $el uptodate and with :width/:height already applied, which rules out (1) as idiomatic / recommended way to integrate < canvas/> drawing with Vue.

That only leaves variant (2) to recommend for < canvas/> drawing with Vue, but I fail to see how loosing the reactivity for drawing from updated() (or setTimeout() / async functions) fits the Vue spirit.

Would it be feasible to add something like vm.$reactive( () => vm.drawcanvas() ) that records reactive data dependencies on vm for a function call the way render() does? Or what other solutions exist that I may be missing?

What does the proposed API look like?

A method vm.$reactive(callback_with_reactivity_working) is just one idea, I'm looking forward to read the Vue designers take on this.

@posva
Copy link
Member

posva commented Aug 23, 2019

The API you are asking for is pretty much covered by the function api and can be also used with Vue.observable

That being said, there won't be native support for canvas as the idea is to expose an api to allow a user land solution like https://github.com/konvajs/vue-konva
In v3 this could also be implemented with custom renderers

@posva posva closed this as completed Aug 23, 2019
@tim-janik
Copy link
Author

The API you are asking for is pretty much covered by the function api and can be also used with Vue.observable

I'm asking for a way so that Vue tracks reactive dependencies outside of render(), because render() cannot be used to draw into a < canvas/>. With Vue.observable, I can just setup additional reactive properties/objects, but this does not help in any way, if there's no way to have Vue track dependencies for draw_canvas() function.

Note that dependency tracking used to work fine in updated() before the changes from #7573 were applied.

That being said, there won't be native support for canvas as the idea is to expose an api to allow a user land solution like https://github.com/konvajs/vue-konva
In v3 this could also be implemented with custom renderers

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

No branches or pull requests

2 participants