-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Poly custom control #8556
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
Merged
Merged
Poly custom control #8556
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 1d51089
refactor(util): export normalizePoint
luizzappa 95e713b
feat(actions): expose PolyControl in fabric.controlsUtils
luizzappa 42c1258
prettier
luizzappa 612a2dd
changelog
luizzappa fd4c5d2
refactor(): rename PolyControl filename
luizzappa b8bfa8d
refactor(): Point#transform instead of the transformPoint function
luizzappa 3ce7430
refactor(): use iMatrix constant
luizzappa 5d2c208
docs(): fix typo and styling
luizzappa eafa394
refactor(): introduce getSize method
luizzappa b8bcb97
refactor(): getLocalPoint instead of normalizePoint
luizzappa e527acc
refactor(PolyControls#createPolyControls): change signature to receiv…
luizzappa f1ab52c
fix(PolyControls): poly with flip
luizzappa e16e64f
minors
ShaMan123 5260d90
Merge branch 'master' into pr/8556
ShaMan123 d9195a4
rm `anchorIndex`
ShaMan123 c6afd8e
`createPolyControls` signature overload
ShaMan123 b806fb9
refactor(polyControl): control interface instead of subclass
luizzappa e6ba30c
remove skew support
luizzappa 0ec0431
Merge branch 'master' into pr/8556
ShaMan123 5464e70
restore signature overloads
ShaMan123 60b31fe
expose
ShaMan123 48dcad2
restore action name
ShaMan123 a6fc8dd
fix(): under group
ShaMan123 5b7f189
Merge branch 'master' into poly-custom-control
asturur File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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), | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| polyObject.calcTransformMatrix() | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| // This function define what the control does. | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // 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 | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // 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( | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| poly, | ||
| new Point(x, y), | ||
| 'center', | ||
| 'center' | ||
| ), | ||
| polygonBaseSize = new Point(poly.width, poly.height), | ||
| size = poly._getTransformedDimensions({}), | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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( | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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(), | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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>, | ||
luizzappa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.