How to manage a canvas using both threejs and fabricjs

My application uses threejs to manage a canvas. For example, to zoom-in/out and pan.
I also added fabricjs for annotation.
The way the app works is that it has a “Renderer” element for threejs, and a “Canvas” element for fabricjs.
Clicking on the Renderer element triggers event on the Canvas element, to which fabricjs responds.
An example of the problem is shown here.

This work well in the “non-freedraw” mode (when the button shows “Enter drawing mode”) when adding, moving, and resizing a shape, e.g. a ractangle or a circle.
But this does not work well in thee “freedraw” mode (when the button shows “Cancel drawing mode”).
In freedraw, when drawing a path, the path is created in the canvas on mousedown, is updated while drawing the mouse, and is finalized on mouseup event.
When the path is finalized, it is shown in the Renderer element - good.
But during the update of the path while the mouse is down and dragged, the updated path is only shown in the Canvas element, but not in the Renderer element.

What needs to be done to show the updated path on the Renderer element while the path is being updated, before it is being finalised?

p.s. the renderer in the link may show as black. May need to “kick” the demo, to show the cube in the renderer, by e.g.

  • toggling the mouse wheel
  • toggling the debugger (F12)

Hey! that is a good feature.
My best guess was try to have an event while the path is being created, but fabricjs don’t have that event type

You need to send the canvas context to the render texture constantly while you’re in a drawing session.
It has nothing to update with without updated textures, you can limit the conversions in an fps clamp to save on memory load, but otherwise its an expenssive task no matter what

You could put the logic into a mousemove event

Fabric.js has a lower and upper canvas, your are rendering (by default) only the lower canvas, for performance reasons the live drawing happens first in the upper canvas (not rendered), then saved and cached to the lower canvas (rendered).

You can see what I mean by switching the rendered canvas in the following line:

  • The lower (default) canvas, what you are using right now:
    texture = new THREE.Texture(document.getElementById("canvas"));
    texture = new THREE.Texture(canvas.lowerCanvasEl);

  • The upper canvas, where the live drawing happen:
    texture = new THREE.Texture(canvas.upperCanvasEl);

Also change the brush color to white so it contrast with the background:
canvas.freeDrawingBrush.color = '#ffffff'

Now how to solve this? Honestly I have no idea! but you’ll probably need to patch fabric itself.

Well building on that upper lower from @Fennec, you can just get whichevers canvas is being updated and send its context to a texture, no need to patch Fabric. If you see something on the screen its drawn and you can capture that context

Heres the core routine for making drawing live work

scroll to the comment // rrr
its changing the texture its pointing to and drawing both canvases

youll need to figure out the offset bug when drawing
Its a scale issue when drawing the the offscreen canvas, youll have to match the proper sizes

Your suggestion to draw the upperCanvas solved the problem.
See a working example in here

p.s. the problem was also reported in here