Skip to content

Commit 481d2c6

Browse files
committed
init
init
1 parent 44a75a3 commit 481d2c6

File tree

5 files changed

+91
-40
lines changed

5 files changed

+91
-40
lines changed

src/canvas/StaticCanvas.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,16 +1352,16 @@ export class StaticCanvas<
13521352
* @example <caption>Generate dataURL with objects that overlap a specified object</caption>
13531353
* var myObject;
13541354
* var dataURL = canvas.toDataURL({
1355-
* filter: (object) => object.isContainedWithinObject(myObject) || object.intersectsWithObject(myObject)
1355+
* filter: (object) => object.isOverlapping(myObject)
13561356
* });
13571357
*/
1358-
toDataURL(options = {} as TDataUrlOptions): string {
1359-
const {
1360-
format = 'png',
1361-
quality = 1,
1362-
multiplier = 1,
1363-
enableRetinaScaling = false,
1364-
} = options;
1358+
toDataURL({
1359+
format = 'png',
1360+
quality = 1,
1361+
multiplier = 1,
1362+
enableRetinaScaling = false,
1363+
...options
1364+
}: TDataUrlOptions = {}): string {
13651365
const finalMultiplier =
13661366
multiplier * (enableRetinaScaling ? this.getRetinaScaling() : 1);
13671367

@@ -1379,7 +1379,7 @@ export class StaticCanvas<
13791379
* This is an intermediary step used to get to a dataUrl but also it is useful to
13801380
* create quick image copies of a canvas without passing for the dataUrl string
13811381
* @param {Number} [multiplier] a zoom factor.
1382-
* @param {Object} [options] Cropping informations
1382+
* @param {Object} [options] Cropping information.
13831383
* @param {Number} [options.left] Cropping left offset.
13841384
* @param {Number} [options.top] Cropping top offset.
13851385
* @param {Number} [options.width] Cropping width.
@@ -1388,7 +1388,8 @@ export class StaticCanvas<
13881388
*/
13891389
toCanvasElement(
13901390
multiplier = 1,
1391-
{ width, height, left, top, filter } = {} as TToCanvasElementOptions
1391+
{ width, height, left, top, filter }: Partial<TToCanvasElementOptions> = {},
1392+
canvasEl = createCanvasElement()
13921393
): HTMLCanvasElement {
13931394
const scaledWidth = (width || this.width) * multiplier,
13941395
scaledHeight = (height || this.height) * multiplier,
@@ -1401,7 +1402,6 @@ export class StaticCanvas<
14011402
translateY = (vp[5] - (top || 0)) * multiplier,
14021403
newVp = [newZoom, 0, 0, newZoom, translateX, translateY] as TMat2D,
14031404
originalRetina = this.enableRetinaScaling,
1404-
canvasEl = createCanvasElement(),
14051405
objectsToRender = filter
14061406
? this._objects.filter((obj) => filter(obj))
14071407
: this._objects;

src/shapes/IText/IText.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import {
77
keysMap,
88
keysMapRtl,
99
} from './constants';
10-
import type { TFiller, TOptions } from '../../typedefs';
10+
import type {
11+
ObjectToCanvasElementOptions,
12+
TFiller,
13+
TOptions,
14+
} from '../../typedefs';
1115
import { classRegistry } from '../../ClassRegistry';
1216
import type { SerializedTextProps, TextProps } from '../Text/Text';
1317
import {
@@ -354,7 +358,7 @@ export class IText<
354358
* @override block cursor/selection logic while rendering the exported canvas
355359
* @todo this workaround should be replaced with a more robust solution
356360
*/
357-
toCanvasElement(options?: any): HTMLCanvasElement {
361+
toCanvasElement(options?: ObjectToCanvasElementOptions): HTMLCanvasElement {
358362
const isEditing = this.isEditing;
359363
this.isEditing = false;
360364
const canvas = super.toCanvasElement(options);

src/shapes/Object/Object.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import type {
1919
TCacheCanvasDimensions,
2020
Abortable,
2121
TOptions,
22+
ObjectToCanvasElementOptions,
23+
ObjectToDataUrlOptions,
2224
} from '../../typedefs';
2325
import { classRegistry } from '../../ClassRegistry';
2426
import { runningAnimations } from '../../util/animation/AnimationRegistry';
@@ -1335,7 +1337,7 @@ export class FabricObject<
13351337
* @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2
13361338
* @return {FabricImage} Object cloned as image.
13371339
*/
1338-
cloneAsImage(options: any): FabricImage {
1340+
cloneAsImage(options?: ObjectToCanvasElementOptions): FabricImage {
13391341
const canvasEl = this.toCanvasElement(options);
13401342
// TODO: how to import Image w/o an import cycle?
13411343
const ImageClass = classRegistry.getClass('image');
@@ -1356,23 +1358,30 @@ export class FabricObject<
13561358
* @param {Boolean} [options.viewportTransform] Account for canvas viewport transform
13571359
* @return {HTMLCanvasElement} Returns DOM element <canvas> with the FabricObject
13581360
*/
1359-
toCanvasElement(options: any = {}) {
1361+
toCanvasElement({
1362+
enableRetinaScaling,
1363+
withoutTransform,
1364+
withoutShadow,
1365+
viewportTransform,
1366+
format,
1367+
multiplier,
1368+
canvasElement,
1369+
...options
1370+
}: ObjectToCanvasElementOptions = {}) {
13601371
const origParams = saveObjectTransform(this),
13611372
originalGroup = this.group,
13621373
originalShadow = this.shadow,
1363-
abs = Math.abs,
1364-
retinaScaling = options.enableRetinaScaling
1374+
retinaScaling = enableRetinaScaling
13651375
? Math.max(config.devicePixelRatio, 1)
1366-
: 1,
1367-
multiplier = (options.multiplier || 1) * retinaScaling;
1376+
: 1;
13681377
delete this.group;
1369-
if (options.withoutTransform) {
1378+
if (withoutTransform) {
13701379
resetObjectTransform(this);
13711380
}
1372-
if (options.withoutShadow) {
1381+
if (withoutShadow) {
13731382
this.shadow = null;
13741383
}
1375-
if (options.viewportTransform) {
1384+
if (viewportTransform) {
13761385
sendObjectToPlane(this, this.getViewportTransform());
13771386
}
13781387

@@ -1389,9 +1398,13 @@ export class FabricObject<
13891398
: this.getObjectScaling();
13901399
// consider non scaling shadow.
13911400
shadowOffset.x =
1392-
2 * Math.round(abs(shadow.offsetX) + shadowBlur) * abs(scaling.x);
1401+
2 *
1402+
Math.round(Math.abs(shadow.offsetX) + shadowBlur) *
1403+
Math.abs(scaling.x);
13931404
shadowOffset.y =
1394-
2 * Math.round(abs(shadow.offsetY) + shadowBlur) * abs(scaling.y);
1405+
2 *
1406+
Math.round(Math.abs(shadow.offsetY) + shadowBlur) *
1407+
Math.abs(scaling.y);
13951408
}
13961409
const width = boundingRect.width + shadowOffset.x,
13971410
height = boundingRect.height + shadowOffset.y;
@@ -1404,7 +1417,7 @@ export class FabricObject<
14041417
renderOnAddRemove: false,
14051418
skipOffscreen: false,
14061419
});
1407-
if (options.format === 'jpeg') {
1420+
if (format === 'jpeg') {
14081421
canvas.backgroundColor = '#fff';
14091422
}
14101423
this.setPositionByOrigin(
@@ -1418,7 +1431,11 @@ export class FabricObject<
14181431
canvas._objects = [this];
14191432
this.set('canvas', canvas);
14201433
this.setCoords();
1421-
const canvasEl = canvas.toCanvasElement(multiplier || 1, options);
1434+
const canvasEl = canvas.toCanvasElement(
1435+
(multiplier || 1) * retinaScaling,
1436+
options,
1437+
canvasElement
1438+
);
14221439
this.set('canvas', originalCanvas);
14231440
this.shadow = originalShadow;
14241441
if (originalGroup) {
@@ -1450,7 +1467,7 @@ export class FabricObject<
14501467
* @param {Boolean} [options.withoutShadow] Remove current object shadow. Introduced in 2.4.2
14511468
* @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
14521469
*/
1453-
toDataURL(options: any = {}) {
1470+
toDataURL(options: ObjectToDataUrlOptions = {}) {
14541471
return toDataURL(
14551472
this.toCanvasElement(options),
14561473
options.format || 'png',

src/shapes/Text/Text.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,8 @@ export class FabricText<
11611161

11621162
ctx.save();
11631163
if (currentDirection !== this.direction) {
1164-
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
1164+
// optional check to safeguard when exporting to canvas element in node
1165+
ctx.canvas.setAttribute?.('dir', isLtr ? 'ltr' : 'rtl');
11651166
ctx.direction = isLtr ? 'ltr' : 'rtl';
11661167
ctx.textAlign = isLtr ? LEFT : RIGHT;
11671168
}

src/typedefs.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,50 @@ export type TRectBounds = [min: XY, max: XY];
9999

100100
export type TToCanvasElementOptions<
101101
T extends BaseFabricObject = BaseFabricObject
102-
> = {
103-
left?: number;
104-
top?: number;
105-
width?: number;
106-
height?: number;
107-
filter?: (object: T) => boolean;
102+
> = TBBox & {
103+
filter: (object: T) => boolean;
108104
};
109105

106+
type ToDataUrlExtraOptions = { quality: number };
107+
108+
type ToCanvasElementExtraOptions = {
109+
multiplier: number;
110+
enableRetinaScaling: boolean;
111+
format: ImageFormat;
112+
};
113+
114+
type ObjectToCanvasElementExtraOptions = ToCanvasElementExtraOptions & {
115+
/**
116+
* Remove current object shadow.
117+
*/
118+
withoutShadow: boolean;
119+
/**
120+
* Remove current object transform ( no scale , no angle, no flip, no skew )
121+
*/
122+
withoutTransform: boolean;
123+
/**
124+
* Account for canvas viewport transform
125+
*/
126+
viewportTransform: boolean;
127+
/**
128+
* The element being to used to draw the object onto.
129+
*/
130+
canvasElement: HTMLCanvasElement;
131+
};
132+
133+
export type ObjectToCanvasElementOptions = Partial<
134+
TBBox & ObjectToCanvasElementExtraOptions
135+
>;
136+
137+
export type ObjectToDataUrlOptions = ObjectToCanvasElementOptions &
138+
Partial<ToDataUrlExtraOptions>;
139+
110140
export type TDataUrlOptions<T extends BaseFabricObject = BaseFabricObject> =
111-
TToCanvasElementOptions<T> & {
112-
multiplier: number;
113-
format?: ImageFormat;
114-
quality?: number;
115-
enableRetinaScaling?: boolean;
116-
};
141+
Partial<
142+
TToCanvasElementOptions<T> &
143+
ToCanvasElementExtraOptions &
144+
ToDataUrlExtraOptions
145+
>;
117146

118147
export type Abortable = {
119148
/**

0 commit comments

Comments
 (0)