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.51k stars 1.23k forks source link

View fit bounds of Item. #1688

Open domske opened 5 years ago

domske commented 5 years ago

Is there a way to fit the view to a drawing? There is a method fitBounds of Item. This resizes (scales) the drawing. But I want a method of View to fit the drawing without resizing it.

// e.g.
paper.project.activeLayer.fitBounds(paper.view.bounds.scale(0.9));
// or
group.fitBounds(view.bounds);
// etc.

Demo

Demo instructions: Use the GUI on the top right to draw a path. (e.g. a square) Hit the "Fit to View" button and draw again.

I do not want to scale the drawing. I want to add a new point (0, -100) relative to the last point without calculating the scaled coordinate. I could get the last point and add 100. But I have to scale 100 to the actual scale factor of the drawing. It's not the best method to do this.

I want to fit the view to the drawing. Not the drawing to the view. So I suggest a new feature. The method fitBounds for the View. I do not know how that should work. Zoom, center. Maybe I'm thinking in the wrong direction too.

I just want to fit the view to the drawing while drawing a path. By adding absolute points. This does not work if the drawing is always resized. (See demo) The solution above (item.fitBounds(view.bounds)) works if I call it after complete the drawing, but not while the drawing is in progress. Because it's resized.

demo

Paper version 0.12.3

domske commented 5 years ago

The view.fitBounds() method should do this. view

Set the size to fit the drawing and center. If center is [0, 0] (see the demo from first post) it should work to keep the abolute position. 🤔 ...? Or how to achieve this?

sasensi commented 5 years ago

Hi, this can quite easily be achieved by manipulating view matrix (translation, scale). Here is a sketch demonstrating a possible solution.

var item = new Path.Circle({
    center: [0, 0],
    radius: 50,
    fillColor: 'orange'
});

viewFitBounds(item.bounds)

function viewFitBounds(itemBounds) {
    var viewBounds = view.bounds;
    var scaleRatio = Math.min(
        viewBounds.width / itemBounds.width,
        viewBounds.height / itemBounds.height
    );
    view.translate(viewBounds.center - itemBounds.center);
    view.scale(scaleRatio);
}
domske commented 5 years ago

Thanks @sasensi It works great. 👍 We could implement this to the View class. view.fitBounds. What do you think? Ok, it's not the same as fitBounds of an Item. But it's only a naming issue. ... It's a helpful feature.

domske commented 5 years ago

In TypeScript it's a bit annoying that some properties can be null. e.g. bounds.center or bounds.width etc. It's very challenging in strict mode. These properties should not be optional.

sasensi commented 5 years ago
lehni commented 5 years ago

@sasensi I quite like the idea of adding it that!

sasensi commented 5 years ago

Ok, then I will make a PR adding it soon ! :)