2d graphics library for WASM with viewport functionality

I'm making a VTT for a wargame a friend invented. It's a single-page website mostly written in Vue.
The current renderer written in TypeScript, PixiJS, and pixi-viewport gets slow for large boards. So i resolved to Rewrite It In Rust™.

I need the ability to zoom in and pan and I really don't want to write it myself. So I've been looking for a library which

  • can compile to WASM and render to a HTML canvas
  • includes "viewport" functionality (or an associated crate which adds it)
    • preferably with an example for hooking the viewport up to panning and zooming with the mouse
  • reasonable bundle size

I considered Piet and Jiao but neither seems to have the ability to change the viewport at all

You may not be getting any responses because a "viewport" is just (conceptually) a positioned rectangle. Any rectangle type from any geometry crate will do. When drawing, you just subtract the "viewport" (rectangle) position from the draw destination position [1]. And that's it. You don't need a crate for that.

It's a rectangle because games with tile maps usually don't want the viewport to extend beyond the visible tiles. Its position (and size) must both be clamped to the map size.

Most game engines will incorporate a viewport as a first-class concept, so you don't have to make it a concern in your draw methods [2]. In bevy, the viewport is abstracted behind cameras. ggez gives you a raw projection matrix with a shortcut method. Etc.


  1. There is also layered parallax scrolling, where the viewport position is scaled down by some fraction. Multiplying the viewport position by 0.5 (or equivalently, dividing by 2) makes the layer move half as fast/far as the viewport. For obvious reasons. ↩︎

  2. They work by keeping a "global" transformation matrix for each entity, and the viewport position factors into it automatically when drawing. ↩︎

Zoom and pan, however, can get messy, in my experience. There's a lot of trying to figure out when and where to apply scaling, and how to maintain the center of the zoom. If you don't find one, I suppose I could publish a simple crate to wrap up my attempts?

just subtract the "viewport" (rectangle) position from the draw destination position

None of them seem to have the ability to change the draw destination. That's what I mean by "change the viewport". There's a width and height but no x or y offset.

Bevy does already have bevy_pancam — Rust game dev // Lib.rs which seems like it has all the important bits of zoom and pan of what is rendered.

In that bevy cameras link, you can set the camera viewport.target_position to change where on the target it's drawn.

Is there some other piece missing?


Just to be clear: the standard terminology from 3d APIs is that a render target is some texture or window or whatever you can draw to, a viewport is a sub rectangle of that target so you can draw to only part of it, a camera is an API to describe what to draw, which normally creates both a projection matrix describing the camera settings itself (orthographic vs perspective, zoom, aspect ratio etc) and a view matrix describing the placement of the camera.

It sounds more like you need to be able to position the camera than the viewport proper, in API terms. In other words, you need a viewport onto a map, not a viewport onto the screen. If not, then you have both now!

Of course they do. The ggez link says:

The Rect ’s x and y will define the top-left corner of the screen

In the case of bevy, you give the Camera a Transform component. See Camera2dBundle in bevy::core_pipeline::core_2d - Rust Or use the pancam plugin.

edit: https://bevy-cheatbook.github.io/features/camera.html#the-camera-transform describes how it works in bevy.

Ended up using Bevy and bevy_pancam

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.