Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update(AligningGuidelines): Fix some bugs and add custom features. #10120

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c1054f1
fix(AligningGuidelines): Align guidless changes aspect ratio on snapp…
zhe-he Sep 2, 2024
9523d69
fix(AligningGuidelines): set originX left
zhe-he Sep 2, 2024
a764f5e
fix(AligningGuidelines): Rotate alignment
zhe-he Sep 11, 2024
d581738
fix(AligningGuidelines): Too many shapes will result in too many refe…
zhe-he Sep 23, 2024
1a5e2f1
Merge branch 'master' into fix-aligning-guidelines-uniformScaling
zhe-he Sep 24, 2024
c96219f
update(aligning-guidelines): add comment
zhe-he Sep 24, 2024
d88e5fc
update(aligning-guidelines): add custom options
zhe-he Sep 24, 2024
28861b1
update(aligning-guidelines): remove unused type
zhe-he Sep 24, 2024
bbc55d2
update(aligning-guidelines): add custom contraryOriginMap
zhe-he Sep 24, 2024
4f241b3
update(aligning-guidelines): Remove unused variables
zhe-he Nov 8, 2024
88f7922
update(aligning-guidelines): Handle the case of division by zero
zhe-he Nov 11, 2024
c18d25c
update(aligning-guidelines): Update remarks
zhe-he Nov 11, 2024
a2af8e1
fix(AligningGuidelines): Hold down the altKey to offset
zhe-he Nov 26, 2024
0c390d8
Merge branch 'master' into fix-aligning-guidelines-uniformScaling
asturur Nov 26, 2024
af519ad
update(aligning-guidelines): When only drawing reference points, the …
zhe-he Nov 27, 2024
c41d019
update(AligningGuidelines): flip
zhe-he Dec 6, 2024
e292b86
update(AligningGuidelines): Optimize collection
zhe-he Dec 10, 2024
630cbfd
Merge branch 'master' into fix-aligning-guidelines-uniformScaling
asturur Jan 11, 2025
898950f
update(AligningGuidelines): Add dashed lines and custom endpoints
zhe-he Jan 13, 2025
c947eec
update(AligningGuidelines): Update Export Type
zhe-he Jan 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## [next]

- fix(AligningGuidelines): Too many shapes will result in too many reference lines [#10120] (https://github.com/fabricjs/fabric.js/pull/10120)
- fix(AligningGuidelines): Align guidless changes aspect ratio on snapping when scaling [#10114](https://github.com/fabricjs/fabric.js/issues/10114)

## [6.5.4]

- docs() perf(): Reorder caching conditions for most common scenario and docs fixes. [#10366](https://github.com/fabricjs/fabric.js/pull/10366)
Expand Down
164 changes: 160 additions & 4 deletions extensions/aligning_guidelines/README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,176 @@
## How to use it

```ts
import { initAligningGuidelines } from 'fabric/extensions';
import { AligningGuidelines } from 'fabric/extensions';

const config = {
/** At what distance from the shape does alignment begin? */
margin: 4,
/** Aligning line dimensions */
width: 1,
/** Aligning line color */
color: 'rgb(255,0,0,0.9)',
color: 'rgba(255,0,0,0.9)',
/** Close Vertical line, default false. */
closeVLine: false,
/** Close horizontal line, default false. */
closeHLine: false,
};

const deactivate = initAligningGuidelines(myCanvas, options);
const aligningGuidelines = new AligningGuidelines(myCanvas, options);

// in order to disable alignment guidelines later:

deactivate();
aligningGuidelines.dispose();
```

### custom function

```ts
import { AligningGuidelines } from 'fabric/extensions';
import { FabricObject } from 'fabric';

// You can customize the return graphic, and the example will only compare it with sibling elements
new AligningGuidelines(myCanvas, {
getObjectsByTarget: function (target) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this PR and tried using this function to filter out objects that have properties isGridLine on them
like if (!object.isGridLine) { set.add(object) }
but then no guidelines happened at all
was I using it wrong maybe?

Copy link
Contributor Author

@zhe-he zhe-he Nov 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Smrtnyk
Can you provide a simple demo to reproduce your issue? This will help me locate the problem. Regarding this function, if customized, it means that when moving the target element, it only processes the reference line for the graphical representation of the return value
The input parameter of this function is the current shape being operated on, not a loop representing all shapes.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is what I tried

 initAligningGuidelines(this.canvas, {
         getObjectsByTarget: () => {
             const set = new Set<FabricObject>();
             for (const obj of this.canvas.getObjects()) {
                 if (obj.isGridLine) {
                     continue;
                 }
                 set.add(obj);
             }
             return set;
         },
     });

I have a grid that I toggle, used as a helper when adding shapes
for aligning guidelines I want to ignore all lines in that grid
and I thought I can ignore them if I don't add them to the set that is being returned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Smrtnyk
I wrote the custom code according to your method and found that it works. You can compare it with the demo to see where the differences are.
custom demo

2024-11-08.10.37.59.mov

const set = new Set<FabricObject>();
const p = target.parent ?? target.canvas;
p?.getObjects().forEach((o) => {
set.add(o);
});
// Please remember to exclude yourself, or you will always align with yourself.
set.delete(target);
return set;
},
});
```

```ts
import { AligningGuidelines } from 'fabric/extensions';

// You can customize the alignment point, the example only aligns the TL control point
new AligningGuidelines(myCanvas, {
getPointMap: function (target) {
const tl = target.getCoords().tl;
return { tl };
},
});
```

```ts
import { AligningGuidelines } from 'fabric/extensions';
import { InteractiveFabricObject } from 'fabric';

// deactivate constructor control assignment
InteractiveFabricObject.createControls = function () {
return {};
};
// custom controllers
InteractiveFabricObject.ownDefaults.controls = {
abc: new Control({}),
};

// You can set control points for custom controllers
new AligningGuidelines(myCanvas, {
getPointMap: function (target) {
const abc = target.getCoords().tl;
return { abc };
},
getContraryMap: function (target) {
const abc = target.aCoords.br;
return { abc };
},
contraryOriginMap: {
// If abc is the top-left point, then the reference point is the bottom-right.
abc: ['right', 'bottom'],
},
});
```

```ts
import { AligningGuidelines } from 'fabric/extensions';

// You can close all
new AligningGuidelines(myCanvas, {
closeVLine: true,
closeHLine: true,
getPointMap: function (_) {
return {};
},
});
```

```ts
import { AligningGuidelines } from 'fabric/extensions';

// You can set dashed lines.
// You can adjust the size of endpoint x.
new AligningGuidelines(myCanvas, {
lineDash: [2, 2],
xSize: 10,
});
```

```ts
import { AligningGuidelines } from 'fabric/extensions';

// You can customize drawing line segments. What if you want to draw a Bézier curve?
new AligningGuidelines(myCanvas, {
drawLine(origin, target) {
const ctx = this.canvas.getTopContext();
const viewportTransform = this.canvas.viewportTransform;
const zoom = this.canvas.getZoom();

ctx.save();
ctx.transform(...viewportTransform);
ctx.lineWidth = this.width / zoom;
if (this.lineDash) ctx.setLineDash(this.lineDash);
ctx.strokeStyle = this.color;

ctx.beginPath();
ctx.moveTo(origin.x, origin.y);
const controlPoint1 = { x: (origin.x + target.x) / 3, y: origin.y - 50 }; // 控制点1
const controlPoint2 = { x: (origin.x + target.x) / 3, y: target.y + 50 }; // 控制点2
ctx.bezierCurveTo(
controlPoint1.x,
controlPoint1.y,
controlPoint2.x,
controlPoint2.y,
target.x,
target.y,
);
ctx.stroke();

if (this.lineDash) ctx.setLineDash([]);

this.drawX(origin, -1);
this.drawX(target, 1);

ctx.restore();
},
});
```

```ts
import { AligningGuidelines } from 'fabric/extensions';

// If you don't like the endpoints being "X," you can customize the endpoints. For example, the start point can be a solid circle, and the end point can be a hollow circle.
new AligningGuidelines(myCanvas, {
drawX(point: Point, dir: number) {
const ctx = this.canvas.getTopContext();
const zoom = this.canvas.getZoom();
const size = this.xSize / zoom;

ctx.save();
ctx.translate(point.x, point.y);
ctx.beginPath();
ctx.arc(0, 0, size, 0, Math.PI * 2);
if (dir == -1) {
ctx.fillStyle = this.color;
ctx.fill();
} else {
ctx.stroke();
}
ctx.restore();
},
});
```
10 changes: 0 additions & 10 deletions extensions/aligning_guidelines/constant.ts

This file was deleted.

Loading