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

chore(TS) Remove small mixins that are too small to be worthy of existance #8542

Merged
merged 11 commits into from
Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
2 changes: 0 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ import './src/pattern.class'; // optional pattern
import './src/shadow.class'; // optional shadow
import './src/canvas/static_canvas.class';
import './src/canvas/canvas_events'; // optional interaction
import './src/mixins/canvas_dataurl_exporter.mixin';
import './src/mixins/canvas_serialization.mixin'; // optional serialization
import './src/canvas/canvas_gestures.mixin'; // optional gestures
import './src/mixins/canvas_animation.mixin'; // optional animation
import './src/mixins/canvas_straightening.mixin'; // optional animation
import './src/shapes/Object/FabricObject';
import './src/mixins/object_stacking.mixin'; // removed in #8461
import './src/mixins/stateful.mixin'; // will die soon
Expand Down
113 changes: 109 additions & 4 deletions src/canvas/static_canvas.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import { TCachedFabricObject } from '../shapes/Object/Object';
import { Rect } from '../shapes/rect.class';
import type {
TCornerPoint,
TDataUrlOptions,
TFiller,
TMat2D,
TSize,
TToCanvasElementOptions,
TValidToObjectMethod,
} from '../typedefs';
import { cancelAnimFrame, requestAnimFrame } from '../util/animate';
Expand All @@ -27,7 +29,7 @@ import {
} from '../util/dom_misc';
import { removeFromArray } from '../util/internals';
import { uid } from '../util/internals/uid';
import { createCanvasElement, isHTMLCanvas } from '../util/misc/dom';
import { createCanvasElement, isHTMLCanvas, toDataURL } from '../util/misc/dom';
import { invertTransform, transformPoint } from '../util/misc/matrix';
import { pick } from '../util/misc/pick';
import { matrixToSVG } from '../util/misc/svgParsing';
Expand Down Expand Up @@ -1061,7 +1063,7 @@ export class StaticCanvas<
: null;
return {
version: VERSION,
...pick(this, propertiesToInclude),
...pick(this, propertiesToInclude as (keyof this)[]),
objects: this._objects
.filter((object) => !object.excludeFromExport)
.map((instance) =>
Expand Down Expand Up @@ -1296,9 +1298,9 @@ export class StaticCanvas<
createSVGRefElementsMarkup(): string {
return ['background', 'overlay']
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return ['background', 'overlay']
return (['background', 'overlay'] as const)

will type the array and remove the need for the extra as 'overlayColor' | backgroundColor

Copy link
Contributor

Choose a reason for hiding this comment

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

.map((prop) => {
const fill = this[`${prop}Color`];
const fill = this[`${prop}Color`as ('overlayColor' | `backgroundColor`)];
if (isFiller(fill)) {
const shouldTransform = this[`${prop}Vpt`],
const shouldTransform = this[`${prop}Vpt` as ('overlayVpt' | `backgroundVpt`)] as boolean,
vpt = this.viewportTransform,
object = {
width: this.width / (shouldTransform ? vpt[0] : 1),
Expand Down Expand Up @@ -1643,6 +1645,109 @@ export class StaticCanvas<
return this.renderOnAddRemove && this.requestRenderAll();
}

/**
* Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately
* @param {Object} [options] Options object
* @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
* @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
* @param {Number} [options.multiplier=1] Multiplier to scale by, to have consistent
* @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14
* @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14
* @param {Number} [options.width] Cropping width. Introduced in v1.2.14
* @param {Number} [options.height] Cropping height. Introduced in v1.2.14
* @param {Boolean} [options.enableRetinaScaling] Enable retina scaling for clone image. Introduce in 2.0.0
* @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.
* @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
* @see {@link https://jsfiddle.net/xsjua1rd/ demo}
* @example <caption>Generate jpeg dataURL with lower quality</caption>
* var dataURL = canvas.toDataURL({
* format: 'jpeg',
* quality: 0.8
* });
* @example <caption>Generate cropped png dataURL (clipping of canvas)</caption>
* var dataURL = canvas.toDataURL({
* format: 'png',
* left: 100,
* top: 100,
* width: 200,
* height: 200
* });
* @example <caption>Generate double scaled png dataURL</caption>
* var dataURL = canvas.toDataURL({
* format: 'png',
* multiplier: 2
* });
* @example <caption>Generate dataURL with objects that overlap a specified object</caption>
* var myObject;
* var dataURL = canvas.toDataURL({
* filter: (object) => object.isContainedWithinObject(myObject) || object.intersectsWithObject(myObject)
* });
*/
toDataURL(options = {} as TDataUrlOptions): string {
const { format = 'png', quality = 1, multiplier = 1, enableRetinaScaling = false } = options;
const finalMultiplier = multiplier * (enableRetinaScaling ? this.getRetinaScaling() : 1);

return toDataURL(this.toCanvasElement(finalMultiplier, options), format, quality);
}

/**
* Create a new HTMLCanvas element painted with the current canvas content.
* No need to resize the actual one or repaint it.
* Will transfer object ownership to a new canvas, paint it, and set everything back.
* This is an intermediary step used to get to a dataUrl but also it is useful to
* create quick image copies of a canvas without passing for the dataUrl string
* @param {Number} [multiplier] a zoom factor.
* @param {Object} [options] Cropping informations
* @param {Number} [options.left] Cropping left offset.
* @param {Number} [options.top] Cropping top offset.
* @param {Number} [options.width] Cropping width.
* @param {Number} [options.height] Cropping height.
* @param {(object: fabric.Object) => boolean} [options.filter] Function to filter objects.
*/
toCanvasElement(multiplier = 1, { width, height, left, top, filter } = {} as TToCanvasElementOptions): HTMLCanvasElement {
const scaledWidth = (width || this.width) * multiplier,
scaledHeight = (height || this.height) * multiplier,
zoom = this.getZoom(),
originalWidth = this.width,
originalHeight = this.height,
newZoom = zoom * multiplier,
vp = this.viewportTransform,
translateX = (vp[4] - (left || 0)) * multiplier,
translateY = (vp[5] - (top || 0)) * multiplier,
// @ts-ignore
originalInteractive = this.interactive,
newVp = [newZoom, 0, 0, newZoom, translateX, translateY] as TMat2D,
originalRetina = this.enableRetinaScaling,
canvasEl = createCanvasElement(),
// @ts-ignore
originalContextTop = this.contextTop,
objectsToRender = filter
? this._objects.filter(filter)
: this._objects;
canvasEl.width = scaledWidth;
canvasEl.height = scaledHeight;
// @ts-ignore
this.contextTop = null;
this.enableRetinaScaling = false;
// @ts-ignore
this.interactive = false;
this.viewportTransform = newVp;
this.width = scaledWidth;
this.height = scaledHeight;
this.calcViewportBoundaries();
this.renderCanvas(canvasEl.getContext('2d')!, objectsToRender);
this.viewportTransform = vp;
this.width = originalWidth;
this.height = originalHeight;
this.calcViewportBoundaries();
// @ts-ignore
this.interactive = originalInteractive;
this.enableRetinaScaling = originalRetina;
// @ts-ignore
this.contextTop = originalContextTop;
return canvasEl;
}

/**
* Waits until rendering has settled to destroy the canvas
* @returns {Promise<boolean>} a promise resolving to `true` once the canvas has been destroyed or to `false` if the canvas has was already destroyed
Expand Down
11 changes: 10 additions & 1 deletion src/mixins/canvas_animation.mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ fabric.util.object.extend(
*/
fxRemove: function (object, callbacks) {
callbacks = callbacks || {};

var empty = function () {},
onComplete = callbacks.onComplete || empty,
onChange = callbacks.onChange || empty,
Expand All @@ -110,5 +109,15 @@ fabric.util.object.extend(
},
});
},

/**
* @param {fabric.Object} object Object to straighten
* @return {fabric.Canvas} thisArg
*/
fxStraightenObject: function (object: FabricObject) {
return object.fxStraighten({
onChange: this.requestRenderAllBound,
});
},
}
);
112 changes: 0 additions & 112 deletions src/mixins/canvas_dataurl_exporter.mixin.ts

This file was deleted.

31 changes: 0 additions & 31 deletions src/mixins/canvas_straightening.mixin.ts

This file was deleted.

18 changes: 18 additions & 0 deletions src/typedefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import type { Gradient } from './gradient/gradient.class';
import type { Pattern } from './pattern.class';
import type { Point } from './point.class';
import type { FabricObject } from './shapes/Object/FabricObject';

interface NominalTag<T> {
nominalTag?: T;
Expand Down Expand Up @@ -96,3 +97,20 @@ export type TCacheCanvasDimensions = {
x: number;
y: number;
};

export type TToCanvasElementOptions = {
left?: number;
top?: number
width?: number;
height?: number;
filter?: (object: FabricObject) => boolean
}


export type TDataUrlOptions = TToCanvasElementOptions & {
multiplier: number;
format?: ImageFormat;
quality?: number;
enableRetinaScaling?: boolean;
}

16 changes: 0 additions & 16 deletions test/unit/canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -1334,22 +1334,6 @@
assert.equal(rect.getCenterPoint().x, upperCanvasEl.width / 2, 'object\'s "left" property should correspond to canvas element\'s center');
});

QUnit.test('straightenObject', function(assert) {
assert.ok(typeof canvas.straightenObject === 'function');
var rect = makeRect({ angle: 10 });
canvas.add(rect);
canvas.straightenObject(rect);
assert.equal(rect.get('angle'), 0, 'angle should be coerced to 0 (from 10)');

rect.rotate('60');
canvas.straightenObject(rect);
assert.equal(rect.get('angle'), 90, 'angle should be coerced to 90 (from 60)');

rect.rotate('100');
canvas.straightenObject(rect);
assert.equal(rect.get('angle'), 90, 'angle should be coerced to 90 (from 100)');
});

QUnit.test('toJSON', function(assert) {
assert.ok(typeof canvas.toJSON === 'function');
assert.equal(JSON.stringify(canvas.toJSON()), EMPTY_JSON);
Expand Down
Loading