Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2ae4236
feat(PolyControl): modify the shape of a poly
luizzappa Jan 1, 2023
1d51089
refactor(util): export normalizePoint
luizzappa Jan 1, 2023
95e713b
feat(actions): expose PolyControl in fabric.controlsUtils
luizzappa Jan 1, 2023
42c1258
prettier
luizzappa Jan 1, 2023
612a2dd
changelog
luizzappa Jan 1, 2023
fd4c5d2
refactor(): rename PolyControl filename
luizzappa Jan 2, 2023
b8bfa8d
refactor(): Point#transform instead of the transformPoint function
luizzappa Jan 2, 2023
3ce7430
refactor(): use iMatrix constant
luizzappa Jan 2, 2023
5d2c208
docs(): fix typo and styling
luizzappa Jan 2, 2023
eafa394
refactor(): introduce getSize method
luizzappa Jan 3, 2023
b8bcb97
refactor(): getLocalPoint instead of normalizePoint
luizzappa Jan 3, 2023
e527acc
refactor(PolyControls#createPolyControls): change signature to receiv…
luizzappa Jan 3, 2023
f1ab52c
fix(PolyControls): poly with flip
luizzappa Jan 3, 2023
e16e64f
minors
ShaMan123 Jan 3, 2023
5260d90
Merge branch 'master' into pr/8556
ShaMan123 Jan 3, 2023
d9195a4
rm `anchorIndex`
ShaMan123 Jan 3, 2023
c6afd8e
`createPolyControls` signature overload
ShaMan123 Jan 3, 2023
b806fb9
refactor(polyControl): control interface instead of subclass
luizzappa Jan 6, 2023
e6ba30c
remove skew support
luizzappa Jan 6, 2023
0ec0431
Merge branch 'master' into pr/8556
ShaMan123 Jan 6, 2023
5464e70
restore signature overloads
ShaMan123 Jan 6, 2023
60b31fe
expose
ShaMan123 Jan 6, 2023
48dcad2
restore action name
ShaMan123 Jan 6, 2023
a6fc8dd
fix(): under group
ShaMan123 Jan 6, 2023
5b7f189
Merge branch 'master' into poly-custom-control
asturur Jan 9, 2023
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [next]

- feat(PolyControl): modify the shape of a poly with control points [#8556](https://github.com/fabricjs/fabric.js/pull/8556)
- refactor(TS): `animate` and `AnimationRegistry` to classes [#8297](https://github.com/fabricjs/fabric.js/pull/8297)
BREAKING:
- return animation instance from animate instead of a cancel function and remove `findAnimationByXXX` from `AnimationRegistry`
Expand Down
3 changes: 3 additions & 0 deletions src/controls/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { skewCursorStyleHandler, skewHandlerX, skewHandlerY } from './skew';
import { getLocalPoint, getActionFromCorner } from './util';
import { wrapWithFireEvent } from './wrapWithFireEvent';
import { wrapWithFixedAnchor } from './wrapWithFixedAnchor';
import { PolyControl } from './polycontrol.class'

export {
scaleCursorStyleHandler,
Expand All @@ -42,6 +43,7 @@ export {
getActionFromCorner,
renderCircleControl,
renderSquareControl,
PolyControl,
};

/**
Expand All @@ -68,4 +70,5 @@ fabric.controlsUtils = {
getLocalPoint,
renderCircleControl,
renderSquareControl,
PolyControl,
};
149 changes: 149 additions & 0 deletions src/controls/polycontrol.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { Point } from '../point.class';
import { Control } from './control.class';
import { TMat2D } from '../typedefs';
import { Polyline } from '../shapes/polyline.class';
import { multiplyTransformMatrices, transformPoint } from '../util/misc/matrix';
import { TPointerEvent, Transform } from '../EventTypeDefs';
import { normalizePoint } from './util';
import { degreesToRadians } from '../util/misc/radiansDegreesConversion';
import { TransformActionHandler } from '../EventTypeDefs';

export class PolyControl extends Control {
pointIndex: number;

constructor(options: Partial<Control>, pointIndex: number) {
super(options);
this.pointIndex = pointIndex;
}

static applySkew(point: Point, shear: Point) {
const skewedPoint = new Point();
skewedPoint.y = point.y + point.x * shear.y;
skewedPoint.x = point.x + skewedPoint.y * shear.x;
return skewedPoint;
}

static removeSkew(point: Point, shear: Point) {
const unskewedPoint = new Point();
unskewedPoint.x = point.x - point.y * shear.x;
unskewedPoint.y = point.y - unskewedPoint.x * shear.y;
return unskewedPoint;
}

// This function locate the controls.
// It'll be used both for drawing and for interaction
positionHandler(dim: Point, finalMatrix: TMat2D, polyObject: Polyline) {
const x = polyObject.points[this.pointIndex].x - polyObject.pathOffset.x,
y = polyObject.points[this.pointIndex].y - polyObject.pathOffset.y;
return transformPoint(
{ x: x, y: y },
multiplyTransformMatrices(
polyObject.canvas?.viewportTransform ?? ([1, 0, 0, 1, 0, 0] as TMat2D),
polyObject.calcTransformMatrix()
)
);
}

// This function define what the control does.
// It'll be called on every mouse move after a control has been clicked and is being dragged.
// The function receive as argument the mouse event, the current trasnform object
// and the current position in canvas coordinate
// transform.target is a reference to the current object being transformed,
static polyActionHandler(
eventData: TPointerEvent,
transform: Transform,
x: number,
y: number
) {
const poly = transform.target as Polyline,
currentControl = poly.controls[poly.__corner] as PolyControl,
mouseLocalPosition = normalizePoint(
poly,
new Point(x, y),
'center',
'center'
),
polygonBaseSize = new Point(poly.width, poly.height),
size = poly._getTransformedDimensions({}),
shear = new Point(
Math.tan(degreesToRadians(poly.skewX)),
Math.tan(degreesToRadians(poly.skewY))
);

const skewedPathOffset = PolyControl.applySkew(poly.pathOffset, shear),
finalPointPosition = PolyControl.removeSkew(
mouseLocalPosition
.multiply(polygonBaseSize)
.divide(size)
.add(skewedPathOffset),
shear
);

poly.points[currentControl.pointIndex] = finalPointPosition;
poly.setDimensions();

return true;
}

// Keep the polygon in the same position when we change its `width`/`height`/`top`/`left`
static anchorWrapper(anchorIndex: number, fn: TransformActionHandler) {
return function (
eventData: TPointerEvent,
transform: Transform,
x: number,
y: number
) {
const poly = transform.target as Polyline,
absolutePoint = transformPoint(
new Point(
poly.points[anchorIndex].x - poly.pathOffset.x,
poly.points[anchorIndex].y - poly.pathOffset.y
),
poly.calcTransformMatrix()
),
actionPerformed = fn(eventData, transform, x, y),
polygonBaseSize = poly._getNonTransformedDimensions(),
shear = new Point(
Math.tan(degreesToRadians(poly.skewX)),
Math.tan(degreesToRadians(poly.skewY))
);

const newPosition = PolyControl.applySkew(
new Point(
poly.points[anchorIndex].x,
poly.points[anchorIndex].y
).subtract(poly.pathOffset),
shear
).divide(polygonBaseSize);

poly.setPositionByOrigin(
absolutePoint,
newPosition.x + 0.5,
newPosition.y + 0.5
);
return actionPerformed;
};
}

static createPolyControls(
controlPoints: Array<Point>,
options?: Partial<Control>
) {
const lastControl = controlPoints.length - 1,
controls = controlPoints.reduce((acc, point, index) => {
acc['p' + index] = new PolyControl(
{
actionName: 'modifyPolygon',
actionHandler: PolyControl.anchorWrapper(
index > 0 ? index - 1 : lastControl,
PolyControl.polyActionHandler
),
...options,
},
index
);
return acc;
}, {} as Record<string, PolyControl>);
return controls;
}
}
2 changes: 1 addition & 1 deletion src/controls/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export function findCornerQuadrant(
/**
* @returns the normalized point (rotated relative to center) in local coordinates
*/
function normalizePoint(
export function normalizePoint(
target: FabricObject,
point: Point,
originX: TOriginX,
Expand Down