fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 8.11 kB
Source Map (JSON)
{"version":3,"file":"StackedObject.min.mjs","sources":["../../../../src/shapes/Object/StackedObject.ts"],"sourcesContent":["import type { ObjectEvents } from '../../EventTypeDefs';\nimport type { Group } from '../Group';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { StaticCanvas } from '../../canvas/StaticCanvas';\nimport { ObjectGeometry } from './ObjectGeometry';\nimport type { FabricObject } from './FabricObject';\n\ntype TAncestor = StackedObject | Canvas | StaticCanvas;\ntype TCollection = Group | Canvas | StaticCanvas;\n\nexport type Ancestors =\n | [StackedObject | Group]\n | [StackedObject | Group, ...Group[]]\n | Group[];\n\nexport type AncestryComparison = {\n /**\n * common ancestors of `this` and`other`(may include`this` | `other`)\n */\n common: Ancestors;\n /**\n * ancestors that are of `this` only\n */\n fork: Ancestors;\n /**\n * ancestors that are of `other` only\n */\n otherFork: Ancestors;\n};\n\nexport class StackedObject<\n EventSpec extends ObjectEvents = ObjectEvents\n> extends ObjectGeometry<EventSpec> {\n /**\n * A reference to the parent of the object\n * Used to keep the original parent ref when the object has been added to an ActiveSelection, hence loosing the `group` ref\n */\n declare parent?: Group;\n\n /**\n * Checks if object is descendant of target\n * Should be used instead of {@link Group.contains} or {@link StaticCanvas.contains} for performance reasons\n * @param {TAncestor} target\n * @returns {boolean}\n */\n isDescendantOf(target: TAncestor): boolean {\n const { parent, group } = this;\n return (\n parent === target ||\n group === target ||\n this.canvas === target ||\n // walk up\n (!!parent && parent.isDescendantOf(target)) ||\n (!!group && group !== parent && group.isDescendantOf(target))\n );\n }\n\n /**\n * @returns {Ancestors} ancestors (excluding `ActiveSelection`) from bottom to top\n */\n getAncestors(): Ancestors {\n const ancestors: TAncestor[] = [];\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let parent: TAncestor | undefined = this;\n do {\n parent = parent instanceof StackedObject ? parent.parent : undefined;\n parent && ancestors.push(parent);\n } while (parent);\n return ancestors as Ancestors;\n }\n\n /**\n * Compare ancestors\n *\n * @param {StackedObject} other\n * @returns {AncestryComparison} an object that represent the ancestry situation.\n */\n findCommonAncestors<T extends this>(other: T): AncestryComparison {\n if (this === other) {\n return {\n fork: [],\n otherFork: [],\n common: [this, ...this.getAncestors()],\n } as AncestryComparison;\n }\n const ancestors = this.getAncestors();\n const otherAncestors = other.getAncestors();\n // if `this` has no ancestors and `this` is top ancestor of `other` we must handle the following case\n if (\n ancestors.length === 0 &&\n otherAncestors.length > 0 &&\n this === otherAncestors[otherAncestors.length - 1]\n ) {\n return {\n fork: [],\n otherFork: [\n other,\n ...otherAncestors.slice(0, otherAncestors.length - 1),\n ],\n common: [this],\n } as AncestryComparison;\n }\n // compare ancestors\n for (let i = 0, ancestor; i < ancestors.length; i++) {\n ancestor = ancestors[i];\n if (ancestor === other) {\n return {\n fork: [this, ...ancestors.slice(0, i)],\n otherFork: [],\n common: ancestors.slice(i),\n } as AncestryComparison;\n }\n for (let j = 0; j < otherAncestors.length; j++) {\n if (this === otherAncestors[j]) {\n return {\n fork: [],\n otherFork: [other, ...otherAncestors.slice(0, j)],\n common: [this, ...ancestors],\n } as AncestryComparison;\n }\n if (ancestor === otherAncestors[j]) {\n return {\n fork: [this, ...ancestors.slice(0, i)],\n otherFork: [other, ...otherAncestors.slice(0, j)],\n common: ancestors.slice(i),\n } as AncestryComparison;\n }\n }\n }\n // nothing shared\n return {\n fork: [this, ...ancestors],\n otherFork: [other, ...otherAncestors],\n common: [],\n } as AncestryComparison;\n }\n\n /**\n *\n * @param {StackedObject} other\n * @returns {boolean}\n */\n hasCommonAncestors<T extends this>(other: T): boolean {\n const commonAncestors = this.findCommonAncestors(other);\n return commonAncestors && !!commonAncestors.common.length;\n }\n\n /**\n *\n * @param {FabricObject} other object to compare against\n * @returns {boolean | undefined} if objects do not share a common ancestor or they are strictly equal it is impossible to determine which is in front of the other; in such cases the function returns `undefined`\n */\n isInFrontOf<T extends this>(other: T): boolean | undefined {\n if (this === other) {\n return undefined;\n }\n const ancestorData = this.findCommonAncestors(other);\n\n if (ancestorData.fork.includes(other as any)) {\n return true;\n }\n if (ancestorData.otherFork.includes(this as any)) {\n return false;\n }\n // if there isn't a common ancestor, we take the canvas.\n // if there is no canvas, there is nothing to compare\n const firstCommonAncestor = ancestorData.common[0] || this.canvas;\n if (!firstCommonAncestor) {\n return undefined;\n }\n const headOfFork = ancestorData.fork.pop(),\n headOfOtherFork = ancestorData.otherFork.pop(),\n thisIndex = (firstCommonAncestor as TCollection)._objects.indexOf(\n headOfFork as any\n ),\n otherIndex = (firstCommonAncestor as TCollection)._objects.indexOf(\n headOfOtherFork as any\n );\n return thisIndex > -1 && thisIndex > otherIndex;\n }\n}\n"],"names":["StackedObject","ObjectGeometry","isDescendantOf","target","parent","group","this","canvas","getAncestors","ancestors","undefined","push","findCommonAncestors","other","fork","otherFork","common","otherAncestors","length","slice","ancestor","i","j","hasCommonAncestors","commonAncestors","isInFrontOf","ancestorData","includes","firstCommonAncestor","headOfFork","pop","headOfOtherFork","thisIndex","_objects","indexOf","otherIndex"],"mappings":"0DA8BO,MAAMA,UAEHC,EAaRC,cAAAA,CAAeC,GACb,MAAMC,OAAEA,EAAMC,MAAEA,GAAUC,KAC1B,OACEF,IAAWD,GACXE,IAAUF,GACVG,KAAKC,SAAWJ,KAEbC,GAAUA,EAAOF,eAAeC,MAChCE,GAASA,IAAUD,GAAUC,EAAMH,eAAeC,EAEzD,CAKAK,YAAAA,GACE,MAAMC,EAAyB,GAE/B,IAAIL,EAAgCE,KACpC,GACEF,EAASA,aAAkBJ,EAAgBI,EAAOA,YAASM,EAC3DN,GAAUK,EAAUE,KAAKP,SAClBA,GACT,OAAOK,CACT,CAQAG,mBAAAA,CAAoCC,GAClC,GAAIP,OAASO,EACX,MAAO,CACLC,KAAM,GACNC,UAAW,GACXC,OAAQ,CAACV,QAASA,KAAKE,iBAG3B,MAAMC,EAAYH,KAAKE,eACjBS,EAAiBJ,EAAML,eAE7B,GACuB,IAArBC,EAAUS,QACVD,EAAeC,OAAS,GACxBZ,OAASW,EAAeA,EAAeC,OAAS,GAEhD,MAAO,CACLJ,KAAM,GACNC,UAAW,CACTF,KACGI,EAAeE,MAAM,EAAGF,EAAeC,OAAS,IAErDF,OAAQ,CAACV,OAIb,IAAK,IAAWc,EAAPC,EAAI,EAAaA,EAAIZ,EAAUS,OAAQG,IAAK,CAEnD,GADAD,EAAWX,EAAUY,GACjBD,IAAaP,EACf,MAAO,CACLC,KAAM,CAACR,QAASG,EAAUU,MAAM,EAAGE,IACnCN,UAAW,GACXC,OAAQP,EAAUU,MAAME,IAG5B,IAAK,IAAIC,EAAI,EAAGA,EAAIL,EAAeC,OAAQI,IAAK,CAC9C,GAAIhB,OAASW,EAAeK,GAC1B,MAAO,CACLR,KAAM,GACNC,UAAW,CAACF,KAAUI,EAAeE,MAAM,EAAGG,IAC9CN,OAAQ,CAACV,QAASG,IAGtB,GAAIW,IAAaH,EAAeK,GAC9B,MAAO,CACLR,KAAM,CAACR,QAASG,EAAUU,MAAM,EAAGE,IACnCN,UAAW,CAACF,KAAUI,EAAeE,MAAM,EAAGG,IAC9CN,OAAQP,EAAUU,MAAME,GAG9B,CACF,CAEA,MAAO,CACLP,KAAM,CAACR,QAASG,GAChBM,UAAW,CAACF,KAAUI,GACtBD,OAAQ,GAEZ,CAOAO,kBAAAA,CAAmCV,GACjC,MAAMW,EAAkBlB,KAAKM,oBAAoBC,GACjD,OAAOW,KAAqBA,EAAgBR,OAAOE,MACrD,CAOAO,WAAAA,CAA4BZ,GAC1B,GAAIP,OAASO,EACX,OAEF,MAAMa,EAAepB,KAAKM,oBAAoBC,GAE9C,GAAIa,EAAaZ,KAAKa,SAASd,GAC7B,OAAO,EAET,GAAIa,EAAaX,UAAUY,SAASrB,MAClC,OAAO,EAIT,MAAMsB,EAAsBF,EAAaV,OAAO,IAAMV,KAAKC,OAC3D,IAAKqB,EACH,OAEF,MAAMC,EAAaH,EAAaZ,KAAKgB,MACnCC,EAAkBL,EAAaX,UAAUe,MACzCE,EAAaJ,EAAoCK,SAASC,QACxDL,GAEFM,EAAcP,EAAoCK,SAASC,QACzDH,GAEJ,OAAOC,GAAa,GAAKA,EAAYG,CACvC"}