🚧 Under construction 🚧

The Solar System, with Rust & WASM

This is an ongoing project to build a simple model of the solar system. I will use a HTML canvas as a background and try and do all the processing using a web assembly module.

Motivation

I’ve been trying to learn Rust for a few years now, I’ve done a couple of example projects (the wasm-game-of-life) and a desktop alarm/timer app, but nothing substantial.

I’ve also wanted to create my own website where I could showcase my projects. This is the first project on that journey. I have a lot of work ahead to make the site look good. So I’m trying to keep the scope of this project fairly limited.

Tasks

Sources

I got most of the information and code examples from the wasm-bindgen docs, which has a handy canvas example. I also used the wasm-game-of-life docs; which was helpful, but my main aim here is to control the canvas with WASM code, not with JavaScript. So I only used a couple of snippets from there.

Setup

The first part of this project is laying the foundations of our WASM module. Testing to see if we can export functions and control the canvas. If we can render the Sun in the center of the canvas, that’s a good start.

Here’s the cargo.toml for the project:

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
js-sys = "0.3.59"
wasm-bindgen = "0.2.82"

[dependencies.web-sys]
version = "0.3.4"
features = [
  'CanvasRenderingContext2d',
  'Document',
  'Element',
  'HtmlCanvasElement',
  'Window',
]

With this, we can create a quick function to check our WASM code works:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn get_size(canvas_id: &str) {
  let document = web_sys::window().unwrap().document().unwrap();
  let canvas = document.get_element_by_id(canvas_id).unwrap();
  let canvas: web_sys::HtmlCanvasElement = canvas
      .dyn_into::<web_sys::HtmlCanvasElement>()
      .map_err(|_| ())
      .unwrap();

  // console_log macro copied from the wasm-game-of-life
  console_log!("Width: {}\nHeight: {}", canvas.width(), canvas.height());
}

A simplified example of calling the get_size function on the JavaScript side of our code:

import initWasm, { get_size } from '../../../projects/rust-wasm/space-simulation/pkg/space_simulation';

const setupCanvas = async () => {
  await initWasm()
  get_size('space-sim-canvas')
};

// Output:
// Width: 820
// Height: 410

I am using React to render the canvas. The initWasm function is actually called as part of a custom hook. I might cover that in more detail in another post. But as long as you follow the above process you should have the same output.

Birth of a Star

Now, we have created a WASM module that exposes a function to JavaScript, where we can pass a string (the canvas ID) to the module, which can interact with the canvas.

Time to draw our first celestial body, the Sun!

Created: 28/08/2022
Last Updated: 14/09/2022