Will Elm be OK for heavy canvas application?

Hi,

I’m researching if Elm will be a good choice here for a canvas heavy web application.

It involves the following:

  1. Creating “object” on the canvas that can handle clicks, drag and drop, double-click.
  2. Object, say a rectangle, can be drop onto another rectangle and they would merge. Will Elm be able to receive any message on the drop event in the update function?
  3. I find this library: elm-canvas 4.2.1 it seems it want to repaint the entire canvas, I’m not sure my scenario (allow drag and drop) would work there.

Another aspect is maybe I’m approaching the problem in a wrong way. Maybe the canvas element is not the proper choice here.

My 2nd idea would be to use a div container with “object” being drawn from SVG and have the position being absolute.

The second solution seems to be more Elm friendly I think, where the drag and drop would occur on the SVG elements.

I know it’s not much, but I’d like to know earlier than later that Elm would be more painful that not, even though I’d highly prefer using Elm.

Any thoughts, anyone created an app with dynamically positioned elements that can be drag and drop on top of each other.

Thanks

Hi @dstpierre quite some time ago (the app is elm 0.18) I’ve been experimenting with drawing thing in canvas-like environments, see https://elm-image-annotation.pizenberg.fr/. There was no editing of objects though and no drag and drop behavior. It was based on SVG.

Regarding drag and drop, one advice would be to avoid anything directly based on html5 drag-and-drop. It is full of problems, and for this reason, libraries usually create their own way of drag and dropping with object detection and all. In elm this almost certainly means that you’ll have to wire some message passing in your update.

Regarding Canvas. The canvas drawing API cannot be easily used in elm because it is based on side effects (draw this, draw that, clear, change color, etc.). SVG is a declarative API and thus better suited for everything vector drawing in elm. You can also visualize raster images as shown in the linked app but its not handled as well as in canvas, where every thing is rasterized. I believe joakin/elm-canvas is using a nice trick consisting in setting up a custom element web component, needed in addition to the elm package, and communicating with it through the element attributes. I don’t know how much “drawing bandwidth” it can sustain, so you’d have to benchmark it. You could also add your own attributes and events to the custom element to handle the clicking and drag-and-drop behavior in JavaScript land.

Another option is to use elm-explorations/webgl which can be paired with ianmackenzie/elm-3d-scene. But then, you’ll want to be very careful with how you “pack” you object to minimize draw calls.

So lot’s of options :slight_smile: but for each one, probably more work than you were hoping I think.

1 Like

You might be interested in checking out Kite, which is implemented in SVG and is open source.

In general you should figure out if you need Canvas or if SVG is fine. Specifically, you will want to answer these questions:

  • Do you need to do pixel level manipulation of the drawings?
  • Do you need to work with video?
  • Do you need to draw/animate more than ~1000 shapes?

If so, you will likely need canvas and Elm might not be the best choice. Otherwise, SVG is a fine choice and would work well.

3 Likes

If you compare how well the canvas API is supported between different solutions (Elm/React/Vanilla), IMO Elm doesn’t give you much.
Nevertheless, any time I could I reached for Elm, just because of the benefits from the language itself.

I’d suggest using joakin’s elm-canvas. It worked quite well.

One limitation with always bit me when I tried to do canvas-based stuff was text rendering with text metrics: If you plan on having text as one of the elements on your canvas, you’ll likely want to have some information about what size your text is. This information is really hard to obtain with the canvas api in general (so this is not related to the question whether to use Elm or not).

In these cases, I find it’s hard to find solutions. If the text metrics API that vanilla JS gives you is enough (keep in mind this API is not easily accessible from Elm, even with elm-canvas), you’re lucky and I’d suggest using canvas.
Otherwise, try to go native, or - if you’re really ambitious - you can try something like canaskit (but keep in mind that it’s not mature yet).

Good luck with your canvas heavy web application! :slight_smile: I love these kinds of web apps.

2 Likes

I’m tempted to say that Elm isn’t well suited for working with canvas, but I have had a nice time when I have. I made this paint app years ago in Elm 0.18 and canvas: www.ctpaint.org/app

joakin/elm-canvas is great. If for some reason that doesnt suit your needs, I have had a nice time writing something in JS called a CanvasManager that receives port messages from Elm about what canvas operations to apply to what canvas.

So, I imagine an api like:

type CanvasOperation
    = PutPixel Position Color
    | Fill Color

msgToCanvasManager : { htmlId : String } -> List CanvasOperation -> Cmd msg

Then on the JS side, something like

const canvas = document.getElementById(msg.htmlId);

const ctx = canvas.getContext('2d');

switch (msg.operation.type) {
    case "fill":
        ctx.fill();
        break;

    case "put pixel":
        ctx.getImageData();
        // ..
        // I cant remember the canvas api right now
        // but hopefully you can see the idea
        break;
}
1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.