fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 17.1 kB
Source Map (JSON)
{"version":3,"file":"Collection.min.mjs","sources":["../../src/Collection.ts"],"sourcesContent":["import type { Constructor, TBBox } from './typedefs';\nimport { removeFromArray } from './util/internals/removeFromArray';\nimport { Point } from './Point';\nimport type { ActiveSelection } from './shapes/ActiveSelection';\nimport type { Group } from './shapes/Group';\nimport type { InteractiveFabricObject } from './shapes/Object/InteractiveObject';\nimport type { FabricObject } from './shapes/Object/FabricObject';\n\nexport const isCollection = (\n fabricObject?: FabricObject,\n): fabricObject is Group | ActiveSelection => {\n return !!fabricObject && Array.isArray((fabricObject as Group)._objects);\n};\n\nexport function createCollectionMixin<TBase extends Constructor>(Base: TBase) {\n class Collection extends Base {\n /**\n * @type {FabricObject[]}\n * @TODO needs to end up in the constructor too\n */\n _objects: FabricObject[] = [];\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _onObjectAdded(object: FabricObject) {\n // subclasses should override this method\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _onObjectRemoved(object: FabricObject) {\n // subclasses should override this method\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _onStackOrderChanged(object: FabricObject) {\n // subclasses should override this method\n }\n\n /**\n * Adds objects to collection\n * Objects should be instances of (or inherit from) FabricObject\n * @param {...FabricObject[]} objects to add\n * @returns {number} new array length\n */\n add(...objects: FabricObject[]): number {\n const size = this._objects.push(...objects);\n objects.forEach((object) => this._onObjectAdded(object));\n return size;\n }\n\n /**\n * Inserts an object into collection at specified index\n * @param {number} index Index to insert object at\n * @param {...FabricObject[]} objects Object(s) to insert\n * @returns {number} new array length\n */\n insertAt(index: number, ...objects: FabricObject[]) {\n this._objects.splice(index, 0, ...objects);\n objects.forEach((object) => this._onObjectAdded(object));\n return this._objects.length;\n }\n\n /**\n * Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)\n * @private\n * @param {...FabricObject[]} objects objects to remove\n * @returns {FabricObject[]} removed objects\n */\n remove(...objects: FabricObject[]) {\n const array = this._objects,\n removed: FabricObject[] = [];\n objects.forEach((object) => {\n const index = array.indexOf(object);\n // only call onObjectRemoved if an object was actually removed\n if (index !== -1) {\n array.splice(index, 1);\n removed.push(object);\n this._onObjectRemoved(object);\n }\n });\n return removed;\n }\n\n /**\n * Executes given function for each object in this group\n * A simple shortcut for getObjects().forEach, before es6 was more complicated,\n * now is just a shortcut.\n * @param {Function} callback\n * Callback invoked with current object as first argument,\n * index - as second and an array of all objects - as third.\n */\n forEachObject(\n callback: (\n object: FabricObject,\n index: number,\n array: FabricObject[],\n ) => any,\n ) {\n this.getObjects().forEach((object, index, objects) =>\n callback(object, index, objects),\n );\n }\n\n /**\n * Returns an array of children objects of this instance\n * @param {...String} [types] When specified, only objects of these types are returned\n * @return {Array}\n */\n getObjects(...types: string[]) {\n if (types.length === 0) {\n return [...this._objects];\n }\n return this._objects.filter((o) => o.isType(...types));\n }\n\n /**\n * Returns object at specified index\n * @param {Number} index\n * @return {Object} object at index\n */\n item(index: number) {\n return this._objects[index];\n }\n\n /**\n * Returns true if collection contains no objects\n * @return {Boolean} true if collection is empty\n */\n isEmpty() {\n return this._objects.length === 0;\n }\n\n /**\n * Returns a size of a collection (i.e: length of an array containing its objects)\n * @return {Number} Collection size\n */\n size() {\n return this._objects.length;\n }\n\n /**\n * Returns true if collection contains an object.\\\n * **Prefer using {@link FabricObject#isDescendantOf} for performance reasons**\n * instead of `a.contains(b)` use `b.isDescendantOf(a)`\n * @param {Object} object Object to check against\n * @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`\n * @return {Boolean} `true` if collection contains an object\n */\n contains(object: FabricObject, deep?: boolean): boolean {\n if (this._objects.includes(object)) {\n return true;\n } else if (deep) {\n return this._objects.some(\n (obj) =>\n obj instanceof Collection &&\n (obj as unknown as Collection).contains(object, true),\n );\n }\n return false;\n }\n\n /**\n * Returns number representation of a collection complexity\n * @return {Number} complexity\n */\n complexity() {\n return this._objects.reduce((memo, current) => {\n memo += current.complexity ? current.complexity() : 0;\n return memo;\n }, 0);\n }\n\n /**\n * Moves an object or the objects of a multiple selection\n * to the bottom of the stack of drawn objects\n * @param {fabric.Object} object Object to send to back\n * @returns {boolean} true if change occurred\n */\n sendObjectToBack(object: FabricObject) {\n if (!object || object === this._objects[0]) {\n return false;\n }\n removeFromArray(this._objects, object);\n this._objects.unshift(object);\n this._onStackOrderChanged(object);\n return true;\n }\n\n /**\n * Moves an object or the objects of a multiple selection\n * to the top of the stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @returns {boolean} true if change occurred\n */\n bringObjectToFront(object: FabricObject) {\n if (!object || object === this._objects[this._objects.length - 1]) {\n return false;\n }\n removeFromArray(this._objects, object);\n this._objects.push(object);\n this._onStackOrderChanged(object);\n return true;\n }\n\n /**\n * Moves an object or a selection down in stack of drawn objects\n * An optional parameter, `intersecting` allows to move the object in behind\n * the first intersecting object. Where intersection is calculated with\n * bounding box. If no intersection is found, there will not be change in the\n * stack.\n * @param {fabric.Object} object Object to send\n * @param {boolean} [intersecting] If `true`, send object behind next lower intersecting object\n * @returns {boolean} true if change occurred\n */\n sendObjectBackwards(object: FabricObject, intersecting?: boolean) {\n if (!object) {\n return false;\n }\n const idx = this._objects.indexOf(object);\n if (idx !== 0) {\n // if object is not on the bottom of stack\n const newIdx = this.findNewLowerIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n this._onStackOrderChanged(object);\n return true;\n }\n return false;\n }\n\n /**\n * Moves an object or a selection up in stack of drawn objects\n * An optional parameter, intersecting allows to move the object in front\n * of the first intersecting object. Where intersection is calculated with\n * bounding box. If no intersection is found, there will not be change in the\n * stack.\n * @param {fabric.Object} object Object to send\n * @param {boolean} [intersecting] If `true`, send object in front of next upper intersecting object\n * @returns {boolean} true if change occurred\n */\n bringObjectForward(object: FabricObject, intersecting?: boolean) {\n if (!object) {\n return false;\n }\n const idx = this._objects.indexOf(object);\n if (idx !== this._objects.length - 1) {\n // if object is not on top of stack (last item in an array)\n const newIdx = this.findNewUpperIndex(object, idx, intersecting);\n removeFromArray(this._objects, object);\n this._objects.splice(newIdx, 0, object);\n this._onStackOrderChanged(object);\n return true;\n }\n return false;\n }\n\n /**\n * Moves an object to specified level in stack of drawn objects\n * @param {fabric.Object} object Object to send\n * @param {number} index Position to move to\n * @returns {boolean} true if change occurred\n */\n moveObjectTo(object: FabricObject, index: number) {\n if (object === this._objects[index]) {\n return false;\n }\n removeFromArray(this._objects, object);\n this._objects.splice(index, 0, object);\n this._onStackOrderChanged(object);\n return true;\n }\n\n findNewLowerIndex(\n object: FabricObject,\n idx: number,\n intersecting?: boolean,\n ) {\n let newIdx;\n\n if (intersecting) {\n newIdx = idx;\n // traverse down the stack looking for the nearest intersecting object\n for (let i = idx - 1; i >= 0; --i) {\n if (object.isOverlapping(this._objects[i])) {\n newIdx = i;\n break;\n }\n }\n } else {\n newIdx = idx - 1;\n }\n\n return newIdx;\n }\n\n findNewUpperIndex(\n object: FabricObject,\n idx: number,\n intersecting?: boolean,\n ) {\n let newIdx;\n\n if (intersecting) {\n newIdx = idx;\n // traverse up the stack looking for the nearest intersecting object\n for (let i = idx + 1; i < this._objects.length; ++i) {\n if (object.isOverlapping(this._objects[i])) {\n newIdx = i;\n break;\n }\n }\n } else {\n newIdx = idx + 1;\n }\n\n return newIdx;\n }\n\n /**\n * Given a bounding box, return all the objects of the collection that are contained in the bounding box.\n * If `includeIntersecting` is true, return also the objects that intersect the bounding box as well.\n * This is meant to work with selection. Is not a generic method.\n * @param {TBBox} bbox a bounding box in scene coordinates\n * @param {{ includeIntersecting?: boolean }} options an object with includeIntersecting\n * @returns array of objects contained in the bounding box, ordered from top to bottom stacking wise\n */\n collectObjects(\n { left, top, width, height }: TBBox,\n { includeIntersecting = true }: { includeIntersecting?: boolean } = {},\n ) {\n const objects: InteractiveFabricObject[] = [],\n tl = new Point(left, top),\n br = tl.add(new Point(width, height));\n\n // we iterate reverse order to collect top first in case of click.\n for (let i = this._objects.length - 1; i >= 0; i--) {\n const object = this._objects[i] as unknown as InteractiveFabricObject;\n if (\n object.selectable &&\n object.visible &&\n ((includeIntersecting && object.intersectsWithRect(tl, br)) ||\n object.isContainedWithinRect(tl, br) ||\n (includeIntersecting && object.containsPoint(tl)) ||\n (includeIntersecting && object.containsPoint(br)))\n ) {\n objects.push(object);\n }\n }\n\n return objects;\n }\n }\n\n // https://github.com/microsoft/TypeScript/issues/32080\n return Collection as typeof Collection & TBase;\n}\n"],"names":["isCollection","fabricObject","Array","isArray","_objects","createCollectionMixin","Base","Collection","constructor","super","arguments","_defineProperty","_onObjectAdded","object","_onObjectRemoved","_onStackOrderChanged","add","_len","length","objects","_key","size","this","push","forEach","insertAt","index","_len2","_key2","splice","remove","array","removed","_len3","_key3","indexOf","forEachObject","callback","getObjects","_len4","types","_key4","filter","o","isType","item","isEmpty","contains","deep","includes","some","obj","complexity","reduce","memo","current","sendObjectToBack","removeFromArray","unshift","bringObjectToFront","sendObjectBackwards","intersecting","idx","newIdx","findNewLowerIndex","bringObjectForward","findNewUpperIndex","moveObjectTo","i","isOverlapping","collectObjects","_ref","left","top","width","height","includeIntersecting","undefined","tl","Point","br","selectable","visible","intersectsWithRect","isContainedWithinRect","containsPoint"],"mappings":"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"}