WASM event callback binds blocks browser (Chrome) to re-render (CRP)
See original GitHub issue#19203 # The issue
Okay, so I’ve started developing this svg rendering “engine” in blazor and found kinda strange behavior. I am rendering SVG’s and moving them around with css translate3d
transform, called via JS Interop (literally the only thing that my engine uses from javascript, otherwise it’s all C# - wasm).
First of all, I’ve found out that every event callback invokes blazor re-render and it fires AfterRenderAsync and stuff, that makes sense because you want to render new data on some event change, however I am using events like onmousemove
/ ontouchmove
that only change position which is being invoked via javascript, so I’ve disabled ShouldRender
and enabling it by myself on data change.
So right now i basically hook onmousemove
/ ontouchmove
in blazor, and without re-rendering the component I call JSInterop on clientside to move the elements around, worked almost perfect with mouse so far, but when I’ve added ontouchmove
(that probably fires more frequently?) things started to mess up.
As you can see on this log taken during touch movement, I buffer CSS changes via JSInterop -> requestAnimationFrame and the browser (Chrome) does CRP after I slow my movement down (event is called less frequently) or I completely stop.
(btw don’t mind the Re-rendering canvas thing, i log this on mouseup / touchend and it has nothing to do with browser CRP rendering, tried this, don’t worry)
Here you can even see screenshot, where I back enabled ShouldRender
making the component re-render each mouse/touch move and buffer CSS change AfterRenderAsync
You can check the live demo here: http://blaze.majdatrpkos.cz/, however there is no console logging enabled, works perfectly with mouse move on desktop, the bug occurs only if you have touch-enabled laptop (like I do) or smartphone.
You can check the DOM and see that CSS values on canvas aren’t changing that frequently as move occurs when you drag the canvas itself.
src: https://github.com/majda107/blaze-cards
Knowing this approach has no issues in pure js, I feel like there is something in WASM <-> JS binds that prevent the browser from CRP re-render and fire the event instead, since this loop finishes browser fires another event and this whole thing continues.
Also, this only happens in desktop version Chrome and many android browser, it seems to work perfectly fine in desktop Firefox and desktop touch support (I use touch-enabled laptop).
I am not sure if this is bug or feature, but is there any way to fix this? I think that my ‘app’ has an potential to be WASM built working css svg renderer, but this issue totally buries the idea.
To Reproduce
- Hook
ontouchmove
on blazor component with eitherShouldRender
enabled or disabled - Call JSInterop callback that changes
CSS
property and should becss trigger
- Try to use requestAnimationFrame?
- Use Google Chrome on desktop?
Details
- Blazor clientside (WASM) 3.2.0-preview3.20168.3
- Version 81.0.4044.129 (Official Build) (64-bit)
Issue Analytics
- State:
- Created 3 years ago
- Comments:12 (5 by maintainers)
Once more, thanks a ton.
I’ve downloaded .NET 5 and linked .NET 5 preview Mono-wasm nugget, using
MonoWebAssemblyJSRuntime
in .NET 5 razor library and it seems to be almost as performant as rust/c++ version.It’s definitelly faster, than JSInterop bindinds, probably due to marshalling.
You can check demo here: https://blaze.majdatrpkos.cz/ (use CTRL+SHIFT+R to reload service worker), you can drag canvas, elements and multi-select with SHIFT
It’s not cleanest solution, but seems to work so far, makes me wondering, could guys in microsoft somehow encapsulate
InvokeUnmarshalled
function? If it makes any sense, I can fork blazor and add it as a feature, submitting merge request.Okay so correct me now, I’ve removed everything that relates to SVG and even JS Interop and the issue still persists…
I mean, this is thing that should blazor and wasm handle without any issues and it may even be on a list of features but it’s clearly broken.
Broken code:
https://github.com/majda107/blaze-touch-issue you can examine the entire repo here.
Same issue persists, no SVGs, no JS interop, pure wasm issue. I’ve rewritten entire scenario to JS + Rust wasm and it works flawlessly, so this is definitelly not wasm + chrome issue (can provide the code if interested)
Just as I said and thought, this has to be blazor <-> wasm binding issue and it’s definitelly much bigger thing than ‘svg bug that is planned to fix next sprint’, it affects entire rendering tree -> DOM.
Just plug that code in and see it running on some touch-enabled device… If you further investigate what I’ve written in previous comments, you’ll find out it’s not touchevent or something else related stuff btw…
Blazor / WASM just seems to block browser rendering at all in some way,