CanvasKit – Skia and WebAssembly
skia.org
skia.org
Think of the pixels!
/s
Seriously though I believe it's often done to make infinite scrolling and scroll-transitions more visually pleasant. (Not that I agree with the sentiment, but if visuals are more important than anything else...)
There's basically nothing on the website but the API. No decent overview or tutorial or even why someone would want to use this project.
However, from what I understand, there seems to be two things needed to be noted here:
Skia - a standardised library that can 'render' to different backends - i.e. it can render to OpenGL or SVG or PDFs.
CanvasKit (the actual one linked) - basically use Skia on the web (with webgl).
A huge boon here would be performance. For example, in WebGL, if you want to draw text, the current method is actually to render it in the canvas first, and reupload the texture to the GPU. From what I understand Skia seems to handle the rendering 'natively' so this step is not necessary. So basically it would just make it easier to draw 'primitives' since they are provided by the Skia API without having to do workarounds or writing really low level webgl fragments/shaders.
This is just from what I gathered, but yeah it is confusing. If anyone knowledgeable reads this, let me know if I got anything wrong!
Why you would want to use this over HTML5 canvas? Good question. Maybe you want some features in Skia that aren't in the canvas API? Maybe you have a Skia app that you want to port to the web?
For example, Flutter uses it to draw its UIs and Chrome uses it for almost everything, including rendering text parsed from HTML. Sublime Text, Firefox, Xamarin and many other projects also rely on Skia for the same sort of thing.
However, unlike, let's say, Qt or GTK+, Skia does not provide already done widgets (i.e., drop-in buttons, windows, text inputs etc.). It's like the fundamental building block on top of which you can create your buttons, animations and everything else and then display it on screen.
Now, CanvasKit is Skia ported to the browser via WebAssembly. Since Skia is a mature project and very performant (as you can guess from who is using it), it's now an alternative to Canvas API and DOM to render things on websites and will also let existing native applications to be ported to the web more easily.
canvas.getContext('webgl', {desynchronized: true})
The latency of that example seems great with a mouse, and a little laggy with a pen (a bit better than a pure canvas drawing app I've been working on). The frame rate is much better than my app.
https://meta.discourse.org/t/plugin-for-animated-stickers/12...
Presumably having Skia available in the browser makes supporting the web platform easier.
Skia Path Ops : High Performance Set Operations for Geometry
Where are the docs for CanvasKit?
If you're on desktop it's probably because it's not doing any form of subpixel hinting or AA.
It's both harder to do that in a GL context, and I don't know if there's even any way to get the display's subpixel layout in JS in the first place.
do you mean this?
See the Slug thread from earlier today for context...
Slug: Dynamic GPU Font Rendering and Advanced Text Layout https://news.ycombinator.com/item?id=20475111
WebGL context encapsulated as an SkSurface,
allowing for direct drawing to an HTML canvas.
However, I just discovered this project a few hours ago so I don't know if there's any "gotchas" -- hopefully someone more knowledgeable or on the chrome/skia team will chime in.Running this on one of the examples.
let c=document.querySelector("#canvas");
c.getContext("2d"); >>>> null
c.getContext("webgl"); >>>> WebGLRenderingContext { vertexAttribDivisor: vertexAttribDivisor(), drawArraysInstanced: drawArraysInstanced(), drawElementsInstanced: drawElementsInstanced(), createVertexArray: createVertexArray(), deleteVertexArray: deleteVertexArray(), bindVertexArray: bindVertexArray(), isVertexArray: isVertexArray(), drawBuffers: drawBuffers(), Yu: null, canvas: canvas#canvas }
c.getContext("webgl2"); >>>> null
Of course that doesn't stop it from using any amount of software rendering layers before it hits the canvas, but it's a good sign.
[1] - https://developers.google.com/web/updates/2012/07/Taking-adv... [2] - http://fhtr.org/gravityring/sprites.html
" context: I want to build a tile based view (tiles in x/y dimensions + zoom levels). The content of the tiles is loaded from server (shapes mostly) and rendered into tile images client side. I also want the same tiles prerendered as identical images on the server.
For this I have a feeling that something like skia is the way to go. Skia can be used via wasm bindings. How I would fetch the shapes and render the tiles (or fetch the prerendered ones) transparently and then where to render the tiles into, that is what I am trying to figure out. It feels like multithreading could be very useful here. Right now only chrome appears to support OffscreenCanvas (which can be accessed from webworkers), hence the idea of using skia directly and possibly going a level higher to write whatever kind of multithreaded render logic in rust and run it with wasm and a single "canvas output". Whether skia is the right choice here or not is also something I have yet to figure out
The ultimate goal is quick startup (prerendered tiles) while simultaneously high performance when updating the entire view (=multiple tiles in parallel). This is mostly a learning project for me context: I want to build a tile based view (tiles in x/y dimensions + zoom levels). The content of the tiles is loaded from server (shapes mostly) and rendered into tile images client side. I also want the same tiles prerendered as identical images on the server.
For this I have a feeling that something like skia is the way to go. Skia can be used via wasm bindings. How I would fetch the shapes and render the tiles (or fetch the prerendered ones) transparently and then where to render the tiles into, that is what I am trying to figure out. It feels like multithreading could be very useful here. Right now only chrome appears to support OffscreenCanvas (which can be accessed from webworkers), hence the idea of using skia directly and possibly going a level higher to write whatever kind of multithreaded render logic in rust and run it with wasm and a single "canvas output". Whether skia is the right choice here or not is also something I have yet to figure out
The ultimate goal is quick startup (prerendered tiles) while simultaneously high performance when updating the entire view (=multiple tiles in parallel). This is mostly a learning project for me "
Essentially what I am wondering is if using skia via wasm would allow me to bypass limits on canvas natively (and canvas in webworkers) so that I can render multiple tile images in parallel and then draw them into a single view for the user to interact with. Think google maps or similar but tiles rendered client side
Overall this feels like there might be a better way and I am just not seeing it
https://jsfiddle.skia.org/canvaskit/e7ac983d9859f89aff1b6d38...
Just from a brief parse of the code I don't see how the drink could possibly be transforming the way that it is doing. The renderer - drawFrame in this case - isn't doing any heavy lifting to really make all the side animations (drink splash etc) occur.
It appears that at least with this example, possibly the others (the lego one?) if they work they've hidden a lot of data in the fetched json data. Which seems not great. I mean the drink json (https://storage.googleapis.com/skia-cdn/misc/drinks.json) is not human parse-able so I don't see how they made these examples at all. Maybe they made them in Adobe After Effects and then exported the keyframes as json or something, but there's no tutorial or directions that I can see.
This is incredibly frustrating because a decent canvas tool is sorely needed (generally). Does anyone see what is going on?
EDIT: So they do use lottie files (https://lottiefiles.com/410-lego-loader). But lottie files can already be exported to javascript incredibly easily, so unless you really need the extra performance of WASM this doesn't appear to add anything. Am I still missing something?
Any browser already includes the very same set of graphic primitives that Skia provides. Just to render what you see on the screen right now.
Why not just to expose all that as API for WASM or whatever?
Agree on that. But this is not about Canvas::Graphics.
That is actually what I did in Sciter that is using these libraries for rendering on different platforms - they all have very close feature set - umbrella wrapper is quite simple.
Because browser already contains Skia (or Direct2D). In native (most performant) form.
Why do you need to download and run Skia inside Skia?
Like in my Sciter (https://sciter.com) where you can do
var anyEl = …;
anyEl.paintBackground = function(gfx) {
gfx.fillColor(rgb(0,0,0))
.rectangle(0,0,100cm,100cm);
return true; // to suppress CSS background drawing
}
paintBackground/Content/Foreground methods are called while rendering HTML tree and the `gfx` passed to that function is the very same graphics that is used for rendering HTML/CSS tree.That thing allows to combine immediate mode graphics a la ImGui with retained one to achieve more performant solution at the end.
The same approach can be used with WASM I think.
50KB Gzipped seems like it's just the wrapped JS code, not the .wasm code.
https://github.com/google/skia/blob/master/modules/canvaskit...
I'm not saying you are wrong, but if the NPM package needed more stuff it would be in the package.json, no?
If you just do an npm install of canvaskit-wasm you'll find a 6.4M canvaskit.wasm file. That'd have to be some insane gzip magic to bring that down to 50Kb.
If I gzip the entire canvaskit module (including the font files) I'm getting a size of 3.4M. If I just gzip the .wasm file I get a size of 2.4M.