excalidraw icon indicating copy to clipboard operation
excalidraw copied to clipboard

Feature Enhancement: Define Canvas Size

Open mmmd-am opened this issue 4 years ago • 10 comments
trafficstars

Please allow for defined canvas sizes. It was requested to open a new issue here: https://github.com/excalidraw/excalidraw/issues/38

The infinite scroll is not always ideal.

Would be even better if user/admin could set/load a canvas background and interact with background with custom functions (e.g. custom SVG interactions in an SVG object layer that the canvas sits on top of in the same dimensions, and both the background layer and canvas zoom and pan seamlessly together).

Another example would be: User uploads a photo background, the canvas becomes the size of the photo, and the user can pan and zoom and mark on the photo with excalidraw. The user could use custom photo functions/tools to manipulate the photo background (rotate, crop, change color hue, etc).

mmmd-am avatar Oct 24 '21 01:10 mmmd-am

I have a rough implementation of this feature. It's tailored for my specific use-case, which is: a fixed-size canvas that fills parent container, while maintaining proper aspect ratio, without panning or zooming available.

The UI/UX part is sub-optimal for the excalidraw-app, which should probably still support zooming and panning of the fixed-size canvas.

That being said, the following general-purpose functionality is also implemented:

  • Proper scene initialization based on canvas size mode (fixed or infinite)
  • Proper exporting to SVG / png based on canvas size mode (fixed or infinite). In the fixed size mode it'll export the full canvas of desired size instead of part of the canvas that covers all elements.

Things that are missing:

  • UI for setting canvas size. For now, it's done by the Excalidraw component prop.

How it's done

defaultCanvasSize?: {width: number, height: number} prop was added to Excalidraw component, which enables "fixed size" mode.

I added canvasSize property to AppState:

export type CanvasSize =
  | { mode: "fixed"; width: number; height: number }
  | { mode: "infinite" }
  | { mode: "default" };

The "default" mode is used to tell that it's not being specified yet, so we'll set it to either "fixed" or "infinite" based on whether defaultCanvasSize property was passed to Excalidraw component when we initialize the scene.

When loading an existing document without canvasSize property in the AppState, it's automatically set to "infinite".

josephbuchma avatar Sep 18 '22 07:09 josephbuchma

Awesome @josephbuchma -

Are you saying you disabled panning and zooming? Or it's not available with this solution.

Panning and zooming would still be important to my use case; as would having a background image that pans and zooms with it..

mmmd-am avatar Sep 18 '22 14:09 mmmd-am

Yes, if the scene has a fixed canvas size, panning and zooming are not available. This solution can be extended to support panning and zooming, although will require a bit more work. I didn't bother since I don't need it. But maybe I'm missing something, it's still a work in progress.

josephbuchma avatar Sep 18 '22 18:09 josephbuchma

@mmmd-am I found some shortcomings in my original approach and updated how fixed-size canvas is rendered on the screen - it's more generic, and now it's possible to have pan & zoom if you like:

export type CanvasSize =
  | {
      mode: "fixed";
      width: number;
      height: number;
      autoZoom?: boolean; // pan & zoom is locked if this property is set to true
    }
  | { mode: "infinite" }
  | { mode: "default" };

The UI for setting canvas size is still not there, and UX with fixed canvas and unlocked pan & zoom still need to be polished:

  • It's possible to draw outside of the fixed canvas, although when you export an image, it exports only the "fixed size part" of the canvas.
  • It's possible to move an empty canvas out of the screen and it won't show the "scroll back to content" button.
  • And other small things like canvas positioning when app loads etc...

It mostly works for me as it is right now, so it's unlikely that I'll work on those things in the near future, but it should be fairly easy to pick up for you and get it to the stage where it can be merged.

UPD: I'll probably fix the drawing outside of the fixed canvas thing UPD2: Fixed drawing elements outside of the canvas.

Here is a quick demo of how it works at the moment:

https://user-images.githubusercontent.com/3718145/191666539-5116f454-52d0-421f-b0d4-2f947a58629f.mov

josephbuchma avatar Sep 22 '22 05:09 josephbuchma

@josephbuchma Awesome work. If you are available to discuss privately, please let me know.

mmmd-am avatar Sep 22 '22 13:09 mmmd-am

Hi, great job @josephbuchma. It's actually a feature I was looking for. Any news on if or when It'll be added to Excalidraw ?

alanlima-fr avatar Dec 29 '22 16:12 alanlima-fr

Hey folks! I apologize for not replying @mmmd-am

@alanlima-fr I don't know if this feature is in Excalidraw's roadmap.

I'm working on https://shwif.com which is based on Excalidraw. Initially, I was working on my fork of Excalidraw, but later I moved it to a private repo, which I plan to open source in the future.

Here is an example story created in Shwif - open on a smartphone for the best experience.

Another example (annotations are in Ukrainian, and it's dark there because we're bombed by russia and there is no electricity).

What I'm building differs from Excalidraw quite a lot, so keeping it backward-compatible was slowing me down substantially.

josephbuchma avatar Dec 30 '22 07:12 josephbuchma

We do want to support this in some way. Perhaps the upcoming frames feature could work for this. https://github.com/excalidraw/excalidraw/issues/6044

dwelle avatar Dec 30 '22 14:12 dwelle

Thanks for the reply and the solution you offer @josephbuchma Even though shwif.com looks promising, Excalidraw respond to all the problematic that we have at the office.

@dwelle That's great news, thanks ! Let me know if I can help or contribute in some way, and I'll watch the progress on issue #6044

alanlima-fr avatar Dec 30 '22 14:12 alanlima-fr

@josephbuchma awesome! i'm waiting for it every day

ngthorg avatar Jan 27 '23 07:01 ngthorg

PR #6731 will achieve similar result, limiting the canvas size

hobyte avatar Oct 18 '23 12:10 hobyte