https://windowjs.org is a very similar concept -- it wraps Skia and exposes it as the Canvas API, but also embeds v8 for a very small runtime instead of using Node.
It was my first open-source project, released about 3 years ago.
I had plans to also expose WebGL, audio, etc and make it a viable platform for Javascript-based games on desktop.
Life and other projects happened instead, and development was discontinued. Happy to see this project also making Canvas accessible outside the browser!
> but also embeds v8 for a very small runtime instead of using Node.
By how much does embedding just V8 instead of using Node.js decrease the binary size? Node.js uses V8, does most of Node's binary size come from its runtime and not V8?
I tried browsing the website and GitHub repo to find how many kBs or MBs typically is a Window.js binary, but didn't find an answer.
At Soundslice, we have a custom sheet-music-rendering graphics library in frontend JavaScript/Canvas.
We also need to generate vector PDFs serverside — so we use a node library that speaks the HTML Canvas API and can generate PDFs. This way the result is exactly the same as the rendered sheet music in the web browser. Nice!
The upshot is: this kind of library allows for code reuse in non-browser contexts.
On a related note, I once used puppeteer and headless chrome in a docker image to generate PDF manuals from our web page documentation using the print to PDF feature of headless chrome.
I am not sure if it would be viable to use for thousands of PDF generation per minute but it worked great. I wasted a lot of time trying to find a good lib for HTML->PDF and they all kinda sucked in different ways. The only downside is that the chrome PDF api doesn't have a way to generate a table of contents with page numbers.
There isn’t really anything commonly “native” as powerful as skia for 2D drawing and a big part of skia is using the native graphics effectively, this is why it exists in the first place for browser engines. Besides having one target API is a benefit.
It's portable? What other GPU accelerated 2D rendering library is?
One the one hand this is lower-level. On the other hand, I've used puppeteer as my 2D graphics library. I get Canvas 2D, and WebGL, and WebGPU, and all of HTML/CSS (so Text with effects, background images, CSS transforms, etc). I get image and video loading. I can then use the screenshot functionality to make an image of whatever I put together. It's overkill, but for my use case I don't care. It works, it's cross platform, it solves my problem.
I'd be surprised if you could point out a platform that has better APIs for drawing 2D graphics than Canvas offers. Skia outperforms Direct2D by a little bit and outperforms Cairo by a lot. It is optimized to a high degree and has GPU-accelerated backends.
Being able to run the same code on multiple platforms is a big bonus. It’s also a very common 2D drawing API. iOS has a native version, Android has a native version, all with more or less the same drawing operations. Leveraging them can pay dividends.
Server-side rendering of a track onto map tiles, enriched with other information like PoIs, distance marks, colorizing the track according to the speed, and so on, in order to then send it as a summary email to the customer.
Skia is the most modern library if you want to render shapes onto an image/surface.
According to the example `import {Window} from 'skia-canvas'` you can also use it to draw onto a spawned window on a desktop.
I used it (different lib, same purpose) at a previous startup, shared web whiteboard, to save the whiteboard to pdf/image.
We had a rendering engine backed by canvas, so it was easy to just redirect it to this to get the file output. (not everything was visible on the user's screen all the time so couldn't just save from the client)
Yes I would like to know this too. There are various people saying they use this (or things like it) but nobody is saying what they are actually doing with it.
Skia ships with a WASM build that supports node, called CanvasKit [1], whereas this module is Rust bindings? I’d be keen to know what the pros and cons of each approach are.
Note that it's not so much "rust bindings" as a pre-compiled node binary (that happens to be generated off of a mixed Rust/C++ codebase). So that's really the main difference: WASM needs a separate runtime, whereas a node binary doesn't.
Huh, it's more than just a rendering API: "can render to windows using an OS-native graphics pipeline and provides a browser-like UI event framework". They could add wgpu to get WebGPU support and ANGLE to get WebGL support.
Skia is a widely used library (off the top of my head, Chrome, Firefox, and LibreOffice use it) that supports lots of rendering targets, including WebGPU and ANGLE.
I don't mean WebGPU and WebGL as Skia backends. I mean WebGPU and WebGL as APIs that this library could expose to users in addition to the HTML canvas API.
That's very similar to what Qt already provides (QPainter, for raw image/windows, more sophisticated widgets with event support. Further- and this is something I've been looking for a while- they have a graphicsview that allows resolution-independent rendering of millions of objects, with events, in an larger-than-window graphics plane.
It was my first open-source project, released about 3 years ago.
I had plans to also expose WebGL, audio, etc and make it a viable platform for Javascript-based games on desktop.
Life and other projects happened instead, and development was discontinued. Happy to see this project also making Canvas accessible outside the browser!
The idea was to have TCP sockets and Websockets to enable that.
Basically, have the same APIs you're familiar with in a Browser, but in a much smaller package that you can ship independently of the Browser.
(this is very similar to Electron)
In a drawing tool / library?
That's just asking for trouble. By spec, SVG allows for XXE shenanigans. I'd rather not worry that any image file I process might exfiltrate my data.
> but also embeds v8 for a very small runtime instead of using Node.
By how much does embedding just V8 instead of using Node.js decrease the binary size? Node.js uses V8, does most of Node's binary size come from its runtime and not V8?
I tried browsing the website and GitHub repo to find how many kBs or MBs typically is a Window.js binary, but didn't find an answer.
https://github.com/windowjs/windowjs/releases
About 8 MiB in the end. Note that these builds have a binary trimmed by UPX.
We also need to generate vector PDFs serverside — so we use a node library that speaks the HTML Canvas API and can generate PDFs. This way the result is exactly the same as the rendered sheet music in the web browser. Nice!
The upshot is: this kind of library allows for code reuse in non-browser contexts.
I am not sure if it would be viable to use for thousands of PDF generation per minute but it worked great. I wasted a lot of time trying to find a good lib for HTML->PDF and they all kinda sucked in different ways. The only downside is that the chrome PDF api doesn't have a way to generate a table of contents with page numbers.
Cairo?
One the one hand this is lower-level. On the other hand, I've used puppeteer as my 2D graphics library. I get Canvas 2D, and WebGL, and WebGPU, and all of HTML/CSS (so Text with effects, background images, CSS transforms, etc). I get image and video loading. I can then use the screenshot functionality to make an image of whatever I put together. It's overkill, but for my use case I don't care. It works, it's cross platform, it solves my problem.
Skia is the most modern library if you want to render shapes onto an image/surface.
According to the example `import {Window} from 'skia-canvas'` you can also use it to draw onto a spawned window on a desktop.
We had a rendering engine backed by canvas, so it was easy to just redirect it to this to get the file output. (not everything was visible on the user's screen all the time so couldn't just save from the client)
1. https://www.npmjs.com/package/canvaskit-wasm
FWIW, node ships with a WASM runtime. See https://nodejs.org/en/learn/getting-started/nodejs-with-weba...
https://rust-skia.github.io/doc/skia_safe/canvas/struct.Canv...
[1] https://www.swig.org/
- canvaskit-wasm from the skia project - I don't think it's gpu-accelerated: https://github.com/google/skia/tree/main/modules/canvaskit/n...
- @napi-rs/canvas - This is the fastest binding: https://github.com/Brooooooklyn/canvas?tab=readme-ov-file#pe...
- node-canvas - Uses Cairo instead of Skia: https://github.com/Automattic/node-canvas
It can be added by doing "deno add npm:skia-canvas", adding "nodeModulesDir: auto" to the deno.json, and doing a "deno install --allow-scripts".
[1] https://skia-canvas.org/#rendering-to-a-window