-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
feat(): DrawShape, DrawOval, DrawPoly #8430
Open
ShaMan123
wants to merge
84
commits into
master
Choose a base branch
from
poly-brush2
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 72 commits
Commits
Show all changes
84 commits
Select commit
Hold shift + click to select a range
653946c
svg
ShaMan123 b371499
SHARED_ATTRIBUTES
ShaMan123 a71cfc2
migrate
ShaMan123 e169232
Update circle.class.ts
ShaMan123 b0d0379
Update circle.class.ts
ShaMan123 4e7e498
defaults
ShaMan123 403d791
static
ShaMan123 575af88
Update CHANGELOG.md
ShaMan123 8f64f77
init
ShaMan123 ec4ac19
more
ShaMan123 1c21ea1
m
ShaMan123 4ba47fa
poly
ShaMan123 c66798c
Update polyline.class.ts
ShaMan123 63442ff
more
ShaMan123 fd2afa6
unpleasant
ShaMan123 4b6cc54
imports
ShaMan123 9acdd8d
Merge branch 'master' into ts-poly
ShaMan123 535fee0
Update CHANGELOG.md
ShaMan123 de8b311
more
ShaMan123 66a14cc
revert Point
ShaMan123 65cfcd6
IPoint
ShaMan123 5681fce
refactor `fromElementGenerator` => `polyFromElement`
ShaMan123 1d18a15
Update polyline.class.ts
ShaMan123 ce8660d
Update polyline.class.ts
ShaMan123 f6eb764
remove default points
ShaMan123 b5b5126
abstract methods + tidyup
ShaMan123 c536ecb
Update base_brush.class.ts
ShaMan123 faf374e
Update CHANGELOG.md
ShaMan123 2558035
Update base_brush.class.ts
ShaMan123 7576a6a
feat(): PolyBrush
ShaMan123 6826935
Update PolyBrush.ts
ShaMan123 ef485d5
Update PolyBrush.ts
ShaMan123 63762e8
Merge branch 'master' into ts-poly
ShaMan123 8f9d9d6
Merge branch 'ts-poly' into poly-brush2
ShaMan123 5e1f1fd
feat(): ShapeBrush
ShaMan123 a195dc5
shape brush
ShaMan123 11790a3
Merge branch 'brushes-patch' into poly-brush2
ShaMan123 653ddbb
Update base_brush.class.ts
ShaMan123 be2e508
Update ShapeBrush.ts
ShaMan123 3e8d0f6
Update ellipse.class.ts
ShaMan123 b8f308e
Update ShapeBrush.ts
ShaMan123 2c78623
circular shape brush
ShaMan123 5073ee7
symmetric
ShaMan123 f3dece5
refactor
ShaMan123 4580f41
Update ShapeBaseBrush.ts
ShaMan123 6ae1ea3
rename
ShaMan123 942cf90
Update DrawShapeBase.ts
ShaMan123 3bd0685
Update DrawShapeBase.ts
ShaMan123 62541fd
Update DrawShapeBase.ts
ShaMan123 a936296
Merge branch 'master' into poly-brush2
ShaMan123 4c28bbe
fix use `setBoundingBox`
ShaMan123 31cae7f
Create draw_shapes.js
ShaMan123 39bb29f
extensive tests!
ShaMan123 1e1db9a
expose super class method `transform`
ShaMan123 6062754
shadow
ShaMan123 70c9e0f
Merge branch 'master' into poly-brush2
ShaMan123 4ab566d
Update CHANGELOG.md
ShaMan123 03e4150
imports
ShaMan123 6d182e0
fix merge artifact
ShaMan123 c267640
Update DrawShapeBase.ts
ShaMan123 211bfe7
imports/types
ShaMan123 0d9a685
Merge branch 'master' into poly-brush2
ShaMan123 2e9d441
Merge branch 'master' into poly-brush2
ShaMan123 f23de4f
Merge branch 'master' into poly-brush2
ShaMan123 1e41df3
Merge branch 'master' into poly-brush2
ShaMan123 a2403c0
Merge branch 'master' into poly-brush2
ShaMan123 a3bb345
Merge branch 'master' into poly-brush2
ShaMan123 f49bd78
Merge branch 'master' into poly-brush2
ShaMan123 cafd0b3
fix(): imports after updating from master
ShaMan123 0c47f6a
Merge branch 'master' into poly-brush2
ShaMan123 f53a921
fix merge conflict
ShaMan123 bae043b
Update CHANGELOG.md
ShaMan123 c6f5896
Update base_brush.class.ts
ShaMan123 ea3c88b
Update DrawShapeBase.ts
ShaMan123 62e94e5
Update canvas.class.ts
ShaMan123 d59f41d
better types
ShaMan123 94c4a9e
forgotten
ShaMan123 81a92fe
Merge branch 'master' into poly-brush2
ShaMan123 9093607
export
ShaMan123 e5dc0d2
cleanup
ShaMan123 63af835
Merge branch 'master' into poly-brush2
ShaMan123 d790f4b
Update CHANGELOG.md
ShaMan123 8c0a447
fix imports, merge error
ShaMan123 2b86cde
Merge branch 'master' into poly-brush2
ShaMan123 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 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 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,37 @@ | ||
import { fabric } from '../../HEADER'; | ||
import { Point } from '../point.class'; | ||
import { Ellipse } from '../shapes/ellipse.class'; | ||
import { DrawShape } from './DrawShape'; | ||
|
||
export class DrawOval extends DrawShape<typeof Ellipse> { | ||
builder = Ellipse; | ||
|
||
protected setBounds(a: Point, b: Point) { | ||
const v = b.subtract(a); | ||
const shape = this.shape!; | ||
const d = new Point(Math.abs(v.x), Math.abs(v.y)); | ||
// set radii | ||
if (this.symmetric) { | ||
const r = this.centered | ||
? d.distanceFrom(new Point()) | ||
: Math.max(d.x, d.y) / 2; | ||
shape.set({ rx: r, ry: r }); | ||
} else { | ||
const { x: rx, y: ry } = this.centered ? d : d.scalarDivide(2); | ||
shape.set({ rx, ry }); | ||
} | ||
// set position | ||
if (this.centered) { | ||
shape.setPositionByOrigin(a, 0.5, 0.5); | ||
} else { | ||
// keep a in place | ||
shape.setPositionByOrigin( | ||
a, | ||
-Math.sign(v.x) * 0.5 + 0.5, | ||
-Math.sign(v.y) * 0.5 + 0.5 | ||
); | ||
} | ||
} | ||
} | ||
|
||
fabric.DrawOval = DrawOval; |
This file contains 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,64 @@ | ||
import { fabric } from '../../HEADER'; | ||
import { Point } from '../point.class'; | ||
import { Polygon } from '../shapes/polygon.class'; | ||
import { Polyline } from '../shapes/polyline.class'; | ||
import { DrawShapeBase } from './DrawShapeBase'; | ||
|
||
export class DrawPoly extends DrawShapeBase<Polyline> { | ||
builder = Polygon; | ||
|
||
private addPoint(pointer: Point) { | ||
this.shape!.points.push(pointer); | ||
} | ||
|
||
private replacePoint(pointer: Point) { | ||
this.shape!.points.pop(); | ||
this.addPoint(pointer); | ||
this._render(); | ||
} | ||
|
||
create() { | ||
return new this.builder(); | ||
} | ||
|
||
protected finalize() { | ||
// release interaction | ||
this.canvas._isCurrentlyDrawing = false; | ||
const shape = this.shape; | ||
if (!shape) return; | ||
shape.setBoundingBox(true); | ||
const r = this.width / 2; | ||
shape.set({ | ||
left: shape.left + r, | ||
top: shape.top + r, | ||
}); | ||
super.finalize(); | ||
} | ||
|
||
onMouseDown(pointer: Point) { | ||
if (this.shape) { | ||
this.addPoint(pointer); | ||
} else { | ||
this.build(); | ||
this.addPoint(pointer); | ||
this.addPoint(pointer); | ||
} | ||
} | ||
|
||
onMouseMove(pointer: Point) { | ||
this.replacePoint(pointer); | ||
} | ||
|
||
onMouseUp({ pointer }: { pointer: Point }) { | ||
this.replacePoint(pointer); | ||
this.addPoint(pointer); | ||
return true; | ||
} | ||
|
||
onDoubleClick(pointer: Point) { | ||
this.shape && this.replacePoint(pointer); | ||
this.finalize(); | ||
} | ||
} | ||
|
||
fabric.DrawPoly = DrawPoly; |
This file contains 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,80 @@ | ||
import { fabric } from '../../HEADER'; | ||
import { ModifierKey } from '../EventTypeDefs'; | ||
import { Point } from '../point.class'; | ||
import type { FabricObject } from '../shapes/Object/FabricObject'; | ||
import { Rect } from '../shapes/rect.class'; | ||
import { TBrushEventData } from './base_brush.class'; | ||
import { DrawShapeBase } from './DrawShapeBase'; | ||
|
||
export class DrawShape< | ||
T extends typeof FabricObject<any> = typeof Rect | ||
> extends DrawShapeBase<InstanceType<T>> { | ||
/** | ||
* class to build shape from | ||
*/ | ||
builder: T = Rect as unknown as T; | ||
|
||
/** | ||
* set to `true` for the shape to be centered on mouse/touch down | ||
*/ | ||
centered = false; | ||
|
||
/** | ||
* The event modifier key that makes the brush symmetric. | ||
*/ | ||
modifierKey?: ModifierKey = 'shiftKey'; | ||
|
||
/** | ||
* set to `true` for the shape to be symmetric | ||
*/ | ||
symmetric?: boolean; | ||
|
||
protected start: Point; | ||
|
||
create() { | ||
return new this.builder() as InstanceType<T>; | ||
} | ||
|
||
protected setBounds(a: Point, b: Point) { | ||
const v = b.subtract(a); | ||
const shape = this.shape!; | ||
const d = new Point(Math.abs(v.x), Math.abs(v.y)); | ||
// size | ||
if (this.symmetric) { | ||
const side = | ||
(d.distanceFrom(new Point()) / Math.SQRT2) * (this.centered ? 2 : 1); | ||
shape.set({ width: side, height: side }); | ||
} else { | ||
shape.set({ width: d.x, height: d.y }); | ||
} | ||
// position | ||
if (this.centered) { | ||
shape.setPositionByOrigin(a, 0.5, 0.5); | ||
} else { | ||
// keep a in place | ||
shape.setPositionByOrigin( | ||
a, | ||
-Math.sign(v.x) * 0.5 + 0.5, | ||
-Math.sign(v.y) * 0.5 + 0.5 | ||
); | ||
} | ||
} | ||
|
||
onMouseDown(pointer: Point) { | ||
this.build(); | ||
this.start = pointer; | ||
} | ||
|
||
onMouseMove(pointer: Point, ev: TBrushEventData) { | ||
this.symmetric = this.modifierKey && ev.e[this.modifierKey]; | ||
this.setBounds(this.start, pointer); | ||
this._render(); | ||
} | ||
|
||
onMouseUp(ev: TBrushEventData) { | ||
this.setBounds(this.start, ev.pointer); | ||
this.finalize(); | ||
} | ||
} | ||
|
||
fabric.DrawShape = DrawShape; |
This file contains 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,64 @@ | ||
import { Point } from '../point.class'; | ||
import { Shadow } from '../shadow.class'; | ||
import type { FabricObject } from '../shapes/Object/FabricObject'; | ||
import { BaseBrush } from './base_brush.class'; | ||
|
||
/** | ||
* Declarative shape drawing using pointer events | ||
*/ | ||
export abstract class DrawShapeBase<T extends FabricObject> extends BaseBrush { | ||
shape: T | undefined; | ||
stroke = ''; | ||
fill = ''; | ||
|
||
abstract create(): T; | ||
|
||
protected build() { | ||
this.shape = this.create(); | ||
this.shape.set('canvas', this.canvas); | ||
this.setStyles(); | ||
} | ||
|
||
setStyles() { | ||
this.shape?.set({ | ||
stroke: this.stroke || this.color, | ||
fill: this.fill || this.color, | ||
strokeWidth: this.width, | ||
strokeLineCap: this.strokeLineCap, | ||
strokeMiterLimit: this.strokeMiterLimit, | ||
strokeLineJoin: this.strokeLineJoin, | ||
strokeDashArray: this.strokeDashArray, | ||
shadow: this.shadow ? new Shadow(this.shadow) : undefined, | ||
}); | ||
} | ||
|
||
protected finalize() { | ||
const shape = this.shape; | ||
if (!shape) return; | ||
shape.setCoords(); | ||
this.canvas.fire('before:path:created', { path: shape }); | ||
this.canvas.add(this.shape); | ||
this.canvas.fire('path:created', { path: shape }); | ||
this.canvas.clearContext(this.canvas.contextTop); | ||
this.shape = undefined; | ||
} | ||
|
||
_setBrushStyles() { | ||
this.setStyles(); | ||
} | ||
|
||
transform(ctx: CanvasRenderingContext2D) { | ||
const t = this.canvas.viewportTransform; | ||
const offset = new Point().transform(t); | ||
ctx.transform(t[0], t[1], t[2], t[3], -offset.x, -offset.y); | ||
} | ||
|
||
_render(ctx: CanvasRenderingContext2D = this.canvas.contextTop) { | ||
this.canvas.clearContext(ctx); | ||
ctx.save(); | ||
this.transform(ctx); | ||
this.shape!.transform(ctx); | ||
this.shape!._render(ctx); | ||
ctx.restore(); | ||
} | ||
} |
This file contains 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 |
---|---|---|
|
@@ -5,7 +5,7 @@ import { TEvent } from '../EventTypeDefs'; | |
import type { Shadow } from '../shadow.class'; | ||
import type { Canvas } from '../canvas/canvas_events'; | ||
|
||
type TBrushEventData = TEvent & { pointer: Point }; | ||
export type TBrushEventData = TEvent & { pointer: Point }; | ||
|
||
/** | ||
* @see {@link http://fabricjs.com/freedrawing|Freedrawing demo} | ||
|
@@ -86,6 +86,8 @@ export abstract class BaseBrush { | |
* @returns true if brush should continue blocking interaction | ||
*/ | ||
abstract onMouseUp(ev: TBrushEventData): boolean | void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to change this signature |
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
onDoubleClick(pointer: Point) {} | ||
|
||
/** | ||
* Sets brush styles | ||
|
@@ -101,15 +103,16 @@ export abstract class BaseBrush { | |
ctx.setLineDash(this.strokeDashArray || []); | ||
} | ||
|
||
transform(ctx: CanvasRenderingContext2D) { | ||
ctx.transform(...this.canvas.viewportTransform); | ||
} | ||
|
||
/** | ||
* Sets the transformation on given context | ||
* @param {CanvasRenderingContext2D} ctx context to render on | ||
* @private | ||
*/ | ||
protected _saveAndTransform(ctx: CanvasRenderingContext2D) { | ||
const v = this.canvas.viewportTransform; | ||
ctx.save(); | ||
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]); | ||
this.transform(ctx); | ||
} | ||
|
||
protected needsFullRender() { | ||
|
This file contains 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 |
---|---|---|
@@ -1,5 +1,8 @@ | ||
export * from './base_brush.class'; | ||
export * from './circle_brush.class'; | ||
export * from './DrawOval'; | ||
export * from './DrawPoly'; | ||
export * from './DrawShape'; | ||
export * from './pattern_brush.class'; | ||
export * from './pencil_brush.class'; | ||
export * from './spray_brush.class'; |
This file contains 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 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 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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO #8462