Skip to content

Commit

Permalink
chore(TS): refactored canvas init sequence and functions (#8520)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaMan123 authored Jan 15, 2023
1 parent c976302 commit 24ac116
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 321 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = {
},
],
rules: {
'@typescript-eslint/ban-types': 1,
'@typescript-eslint/ban-ts-comment': 1,
'no-restricted-globals': [
'error',
Expand Down
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]

- chore(TS): refactor canvas init, fix `_initRetinaScaling` regression #8520
- chore(TS): remove all remaining empty declarations [#8593](https://github.com/fabricjs/fabric.js/pull/8593)
- refactor(IText): modernize IText cursor animation based on animation API changes (and fix minor regression) plus leftovers from #8547 [#8583](https://github.com/fabricjs/fabric.js/pull/8583)
- refactor(Canvas, IText): Handle cross instance text editing states to an EditingManager class [#8543](https://github.com/fabricjs/fabric.js/pull/8543)
Expand Down
68 changes: 16 additions & 52 deletions src/canvas/canvas.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,34 +494,16 @@ export class SelectableCanvas<
protected declare _isCurrentlyDrawing: boolean;
declare freeDrawingBrush?: BaseBrush;
declare _activeObject?: FabricObject;
/**
* Constructor
* @param {HTMLCanvasElement | String} el canvas element to initialize instance on
* @param {Object} [options] Options object
* @return {Object} thisArg
*/
constructor(el: string | HTMLCanvasElement, options = {}) {
super(el, options);
}

_init(el: string | HTMLCanvasElement, options = {}) {
this.renderAndResetBound = this.renderAndReset.bind(this);
this.requestRenderAllBound = this.requestRenderAll.bind(this);
this._initStatic(el, options);
protected initElements(el: string | HTMLCanvasElement) {
super.initElements(el);
this._applyCanvasStyle(this.lowerCanvasEl);
this._initWrapperElement();
this._createUpperCanvas();
// @ts-ignore
this._initEventListeners();
this._isRetinaScaling() && this._initRetinaScaling();
this.calcOffset();
this._createCacheCanvas();
}

/**
* @private
*/
_initRetinaScaling() {
protected _initRetinaScaling() {
super._initRetinaScaling();
this.__initRetinaScaling(this.upperCanvasEl, this.contextTop);
}
Expand Down Expand Up @@ -1183,19 +1165,16 @@ export class SelectableCanvas<
}

/**
* Sets dimensions (width, height) of this canvas instance. when options.cssOnly flag active you should also supply the unit of measure (px/%/em)
* @param {Object} dimensions Object with width/height properties
* @param {Number|String} [dimensions.width] Width of canvas element
* @param {Number|String} [dimensions.height] Height of canvas element
* @param {Object} [options] Options object
* @param {Boolean} [options.backstoreOnly=false] Set the given dimensions only as canvas backstore dimensions
* @param {Boolean} [options.cssOnly=false] Set the given dimensions only as css dimensions
* @return {Canvas} thisArg
* Internal use only
* @protected
*/
setDimensions(dimensions: TSize, options?: TCanvasSizeOptions) {
protected _setDimensionsImpl(
dimensions: TSize,
options?: TCanvasSizeOptions
) {
// @ts-ignore
this._resetTransformEventData();
super.setDimensions(dimensions, options);
super._setDimensionsImpl(dimensions, options);
if (this._isCurrentlyDrawing) {
this.freeDrawingBrush &&
this.freeDrawingBrush._setBrushStyles(this.contextTop);
Expand Down Expand Up @@ -1230,7 +1209,7 @@ export class SelectableCanvas<
* @private
* @throws {CANVAS_INIT_ERROR} If canvas can not be initialized
*/
_createUpperCanvas() {
protected _createUpperCanvas() {
const lowerCanvasEl = this.lowerCanvasEl;

// if there is no upperCanvas (most common case) we create one.
Expand All @@ -1249,30 +1228,15 @@ export class SelectableCanvas<
upperCanvasEl.style.cssText = lowerCanvasEl.style.cssText;
this._applyCanvasStyle(upperCanvasEl);
upperCanvasEl.setAttribute('draggable', 'true');
this.contextTop = upperCanvasEl.getContext(
'2d'
) as CanvasRenderingContext2D;
this.contextTop = upperCanvasEl.getContext('2d')!;
}

/**
* @private
*/
_createCacheCanvas() {
protected _createCacheCanvas() {
this.cacheCanvasEl = this._createCanvasElement();
this.cacheCanvasEl.setAttribute('width', `${this.width}`);
this.cacheCanvasEl.setAttribute('height', `${this.height}`);
this.contextCache = this.cacheCanvasEl.getContext(
'2d'
) as CanvasRenderingContext2D;
this.contextCache = this.cacheCanvasEl.getContext('2d')!;
}

/**
* @private
*/
_initWrapperElement() {
if (this.wrapperEl) {
return;
}
protected _initWrapperElement() {
const container = getEnv().document.createElement('div');
container.classList.add(this.containerClass);
this.wrapperEl = wrapElement(this.lowerCanvasEl, container);
Expand All @@ -1289,7 +1253,7 @@ export class SelectableCanvas<
* @private
* @param {HTMLCanvasElement} element canvas element to apply styles on
*/
_applyCanvasStyle(element: HTMLCanvasElement) {
protected _applyCanvasStyle(element: HTMLCanvasElement) {
const width = this.width || element.width,
height = this.height || element.height;

Expand Down
96 changes: 33 additions & 63 deletions src/canvas/canvas_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,6 @@ export class Canvas extends SelectableCanvas {
*/
declare enablePointerEvents: boolean;

/**
* an internal flag that is used to remember if we already bound the events
* @type Boolean
* @private
*/
private declare eventsBound: boolean;

/**
* Holds a reference to a setTimeout timer for event synchronization
* @type number
Expand Down Expand Up @@ -126,16 +119,39 @@ export class Canvas extends SelectableCanvas {

textEditingManager = new TextEditingManager();

/**
* Adds mouse listeners to canvas
* @private
*/
private _initEventListeners() {
// in case we initialized the class twice. This should not happen normally
// but in some kind of applications where the canvas element may be changed
// this is a workaround to having double listeners.
this.removeListeners();
this._bindEvents();
constructor(el: string | HTMLCanvasElement, options = {}) {
super(el, options);
// bind event handlers
(
[
'_onMouseDown',
'_onTouchStart',
'_onMouseMove',
'_onMouseUp',
'_onTouchEnd',
'_onResize',
// '_onGesture',
// '_onDrag',
// '_onShake',
// '_onLongPress',
// '_onOrientationChange',
'_onMouseWheel',
'_onMouseOut',
'_onMouseEnter',
'_onContextMenu',
'_onDoubleClick',
'_onDragStart',
'_onDragEnd',
'_onDragProgress',
'_onDragOver',
'_onDragEnter',
'_onDragLeave',
'_onDrop',
] as (keyof this)[]
).forEach((eventHandler) => {
this[eventHandler] = (this[eventHandler] as Function).bind(this);
});
// register event handlers
this.addOrRemove(addListener, 'add');
}

Expand Down Expand Up @@ -217,47 +233,6 @@ export class Canvas extends SelectableCanvas {
);
}

/**
* @private
*/
private _bindEvents() {
if (this.eventsBound) {
// for any reason we pass here twice we do not want to bind events twice.
return;
}
(
[
'_onMouseDown',
'_onTouchStart',
'_onMouseMove',
'_onMouseUp',
'_onTouchEnd',
'_onResize',
// '_onGesture',
// '_onDrag',
// '_onShake',
// '_onLongPress',
// '_onOrientationChange',
'_onMouseWheel',
'_onMouseOut',
'_onMouseEnter',
'_onContextMenu',
'_onDoubleClick',
'_onDragStart',
'_onDragEnd',
'_onDragProgress',
'_onDragOver',
'_onDragEnter',
'_onDragLeave',
'_onDrop',
] as const
).forEach((eventHandler) => {
// @ts-expect-error dumb TS
this[eventHandler] = this[eventHandler].bind(this);
});
this.eventsBound = true;
}

/**
* @private
* @param {Event} [e] Event object fired on wheel event
Expand Down Expand Up @@ -1676,8 +1651,3 @@ export class Canvas extends SelectableCanvas {
return new Canvas(el);
}
}

// there is an order execution bug if i put this as public property.
Object.assign(Canvas.prototype, {
eventsBound: false,
});
Loading

0 comments on commit 24ac116

Please sign in to comment.