paperjs / paper.js

The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey
http://paperjs.org
Other
14.45k stars 1.22k forks source link

How to resize and reposition PaperJs sketch on a new canvas of different size? #1876

Closed dilipsarkar closed 3 years ago

dilipsarkar commented 3 years ago

I'm creating an application to draw some sketch on top of a background image, persisting the sketch without the background image and display back the sketch along with background image. Image is served separately and drawn as a background raster.

In my canvas, I have a raster image and on top of that I'm making some sketch pointing a part of the background image. After the sketching is done, I'm doing JSON export, excluding background raster image, to persist the sketch. Now when I export it back on a canvas of different size, the sketch is pointing to the different part of the background image. The background raster is positioned with view.center and it's always occupying the full view of the canvas. Is there any way we can proportionally change the sketch, so that the it points to the same point ?

Any help would be appreciated.

Below is an example :

Original Sketch: image

Sketch on a resized canvas: image

willynlabs commented 3 years ago

Sure. I do this all the time in my app (framework).

I use paperjs mostly as the “path modeler” for marking up PDF and JPEG files, many of which represent drawings (output from AutoCAD).

The way I do this is to separate the “background” (as you call it) into its own “document” coordinate space and draw it on a separate canvas, then I draw the paths to a separate (overlay) canvas that is sized to match the background canvas.

By creating and keeping track of a document (background) coordinate system that is based on the type of file (PDF is different from JPEG), I can create the paths in the document’s coordinate system and they will track and redisplay in that coordinate space.

The user can then pan and zoom around and everything stays aligned. Here is an example (showing the drawing and markup at two different zoom factors).

In your case, you just need to understand the coordinate system of the underlying image (which is typically upper left origin with y axis down, which is the canvas coordinate system), and place the drawn paths relative to that coordinate system. When the “size” of the canvas changes, then change the scale of the coordinate system to keep them aligned.

You may need to do this in an “onresize” event handler, but I am not sure if that is your use case or not.

On Nov 20, 2020, at 4:16 AM, Dilip Sarkar notifications@github.com wrote:

I'm creating an application to draw some sketch on top of a background image, persisting the sketch without the background image and display back the sketch along with background image. Image is served separately and drawn as a background raster.

In my canvas, I have a raster image and on top of that I'm making some sketch pointing a part of the background image. After the sketching is done, I'm doing JSON export, excluding background raster image, to persist the sketch. Now when I export it back on a canvas of different size, the sketch is pointing to the different part of the background image. The background raster is positioned with view.center and it's always occupying the full view of the canvas. Is there any way we can proportionally change the sketch, so that the it points to the same point ?

Any help would be appreciated.

Below is an example :

Original Sketch: https://user-images.githubusercontent.com/4329629/99781796-4fb28b80-2b3e-11eb-9d8a-798feecc12b7.png Sketch on a resized canvas: https://user-images.githubusercontent.com/4329629/99781863-6822a600-2b3e-11eb-9246-39f9e42a9ac4.png — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/paperjs/paper.js/issues/1876, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOCISBWHPGCHAMTF752S5IDSQYXWPANCNFSM4T4QLWMQ.

dilipsarkar commented 3 years ago

Thanks @willynlabs . Did you missed out the example attachment? It would be a great help if you can share that ?

I think what you are doing is perhaps something similar to what I'm trying achieve in my application. In my case, I'm using single canvas where background image is drawn using Paperjs Raster element. We are using exportJSON and importJSON APIs to extract and redraw our sketch respectively. Before exporting, we remove the background Raster and after importing we add back the Raster.

willynlabs commented 3 years ago

I don't have a paperscript example to send, but here is a fairly simple explanation.

In your first image, I imagine that paperjs may be scaling the image to fit the canvas, and lets say it is 400 x 250. You then place the paths such that the center of the circle is at 300, 125 (roughly).

In the second image, your canvas is larger, say 600 x 300, so now you need to scale the coordinates of the paths so that they stay 'relative' to the image size. in this example, the scaling would be [600/400, 250/125] which is an unequal scaling, so you will just want to adjust the origins of the geometry rather than the individual segment points.

So, if the center of the circle was at 300, 125, then the new center would be 450, 250.

All of this assumes your image origin is at the upper left and coordinate system is aligned with the canvas.

Hope it makes sense.

[I use paperjs as a "headless" path modeling library in my app, so I don't use paperscript. I will see what it involved in doing this in paperscript and try to find time to tackle an example.]

dilipsarkar commented 3 years ago

Thanks @willynlabs, really appreciate.

Is your above logic expected to work fine for a Layer instead of individual elements? I have tried for the active layer but it doesn’t seem to position appropriately though the resizing of the object is happening fine. Any thought ?

dilipsarkar commented 3 years ago

I'm able to achieve what I wanted to with the below changes. Thanks @willynlabs for your help. Here originalViewSize is the original size on which the actual sketch was created.

Steps:

// Changing view size and calculating scale factor for x & y-axis
paperScope.view.viewSize = new Size(originalViewSize.width + 200, originalViewSize.height + 100);
const xScale = paperScope.view.viewSize.width /originalViewSize.width;
const yScale = paperScope.view.viewSize.height /originalViewSize.height;

// Update  b/g image bounds
backgroundRaster.bounds = paperScope.view.bounds;
paperScope.project.activeLayer.position.x = paperScope.project.activeLayer.position.x * xScale;
paperScope.project.activeLayer.position.y = paperScope.project.activeLayer.position.y * yScale;
paperScope.project.activeLayer.scale(xScale, yScale);
arnoson commented 3 years ago

Great that everything works for you @dilipsarkar, can I close this issue?

dilipsarkar commented 3 years ago

Sure, pls go ahead and close the issue. Thanks for your support.