fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 10.6 kB
Source Map (JSON)
{"version":3,"file":"Shadow.min.mjs","sources":["../../src/Shadow.ts"],"sourcesContent":["import { classRegistry } from './ClassRegistry';\nimport { Color } from './color/Color';\nimport { config } from './config';\nimport { reNum } from './parser/constants';\nimport { Point } from './Point';\nimport type { FabricObject } from './shapes/Object/FabricObject';\nimport type { TClassProperties } from './typedefs';\nimport { uid } from './util/internals/uid';\nimport { pickBy } from './util/misc/pick';\nimport { degreesToRadians } from './util/misc/radiansDegreesConversion';\nimport { toFixed } from './util/misc/toFixed';\nimport { rotateVector } from './util/misc/vectors';\n\n/**\n * Regex matching shadow offsetX, offsetY and blur (ex: \"2px 2px 10px rgba(0,0,0,0.2)\", \"rgb(0,255,0) 2px 2px\")\n * - (?:\\s|^): This part captures either a whitespace character (\\s) or the beginning of a line (^). It's non-capturing (due to (?:...)), meaning it doesn't create a capturing group.\n * - (-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?: This captures the first component of the shadow, which is the horizontal offset. Breaking it down:\n * - (-?\\d+): Captures an optional minus sign followed by one or more digits (integer part of the number).\n * - (?:\\.\\d*)?: Optionally captures a decimal point followed by zero or more digits (decimal part of the number).\n * - (?:px)?: Optionally captures the \"px\" unit.\n * - (?:\\s?|$): Captures either an optional whitespace or the end of the line. This whole part is wrapped in a non-capturing group and marked as optional with ?.\n * - (-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?: Similar to the previous step, this captures the vertical offset.\n\n(\\d+(?:\\.\\d*)?(?:px)?)?: This captures the blur radius. It's similar to the horizontal offset but without the optional minus sign.\n\n(?:\\s+(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?){0,1}: This captures an optional part for the color. It allows for whitespace followed by a component with an optional minus sign, digits, decimal point, and \"px\" unit.\n\n(?:$|\\s): This captures either the end of the line or a whitespace character. It ensures that the match ends either at the end of the string or with a whitespace character.\n */\n// eslint-disable-next-line max-len\n\nconst shadowOffsetRegex = '(-?\\\\d+(?:\\\\.\\\\d*)?(?:px)?(?:\\\\s?|$))?';\n\nconst reOffsetsAndBlur = new RegExp(\n '(?:\\\\s|^)' +\n shadowOffsetRegex +\n shadowOffsetRegex +\n '(' +\n reNum +\n '?(?:px)?)?(?:\\\\s?|$)(?:$|\\\\s)',\n);\n\nexport const shadowDefaultValues: Partial<TClassProperties<Shadow>> = {\n color: 'rgb(0,0,0)',\n blur: 0,\n offsetX: 0,\n offsetY: 0,\n affectStroke: false,\n includeDefaultValues: true,\n nonScaling: false,\n};\n\nexport type SerializedShadowOptions = {\n color: string;\n blur: number;\n offsetX: number;\n offsetY: number;\n affectStroke: boolean;\n nonScaling: boolean;\n type: string;\n};\n\nexport class Shadow {\n /**\n * Shadow color\n * @type String\n * @default\n */\n declare color: string;\n\n /**\n * Shadow blur\n * @type Number\n */\n declare blur: number;\n\n /**\n * Shadow horizontal offset\n * @type Number\n * @default\n */\n declare offsetX: number;\n\n /**\n * Shadow vertical offset\n * @type Number\n * @default\n */\n declare offsetY: number;\n\n /**\n * Whether the shadow should affect stroke operations\n * @type Boolean\n * @default\n */\n declare affectStroke: boolean;\n\n /**\n * Indicates whether toObject should include default values\n * @type Boolean\n * @default\n */\n declare includeDefaultValues: boolean;\n\n /**\n * When `false`, the shadow will scale with the object.\n * When `true`, the shadow's offsetX, offsetY, and blur will not be affected by the object's scale.\n * default to false\n * @type Boolean\n * @default\n */\n declare nonScaling: boolean;\n\n declare id: number;\n\n static ownDefaults = shadowDefaultValues;\n\n static type = 'shadow';\n\n /**\n * @see {@link http://fabricjs.com/shadows|Shadow demo}\n * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetY properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px\")\n */\n constructor(options: Partial<TClassProperties<Shadow>>);\n constructor(svgAttribute: string);\n constructor(arg0: string | Partial<TClassProperties<Shadow>>) {\n const options: Partial<TClassProperties<Shadow>> =\n typeof arg0 === 'string' ? Shadow.parseShadow(arg0) : arg0;\n Object.assign(this, Shadow.ownDefaults, options);\n this.id = uid();\n }\n\n /**\n * @param {String} value Shadow value to parse\n * @return {Object} Shadow object with color, offsetX, offsetY and blur\n */\n static parseShadow(value: string) {\n const shadowStr = value.trim(),\n [, offsetX = 0, offsetY = 0, blur = 0] = (\n reOffsetsAndBlur.exec(shadowStr) || []\n ).map((value) => parseFloat(value) || 0),\n color = (shadowStr.replace(reOffsetsAndBlur, '') || 'rgb(0,0,0)').trim();\n\n return {\n color,\n offsetX,\n offsetY,\n blur,\n };\n }\n\n /**\n * Returns a string representation of an instance\n * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\n * @return {String} Returns CSS3 text-shadow declaration\n */\n toString() {\n return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n }\n\n /**\n * Returns SVG representation of a shadow\n * @param {FabricObject} object\n * @return {String} SVG representation of a shadow\n */\n toSVG(object: FabricObject) {\n const offset = rotateVector(\n new Point(this.offsetX, this.offsetY),\n degreesToRadians(-object.angle),\n ),\n BLUR_BOX = 20,\n color = new Color(this.color);\n let fBoxX = 40,\n fBoxY = 40;\n\n if (object.width && object.height) {\n //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion\n // we add some extra space to filter box to contain the blur ( 20 )\n fBoxX =\n toFixed(\n (Math.abs(offset.x) + this.blur) / object.width,\n config.NUM_FRACTION_DIGITS,\n ) *\n 100 +\n BLUR_BOX;\n fBoxY =\n toFixed(\n (Math.abs(offset.y) + this.blur) / object.height,\n config.NUM_FRACTION_DIGITS,\n ) *\n 100 +\n BLUR_BOX;\n }\n if (object.flipX) {\n offset.x *= -1;\n }\n if (object.flipY) {\n offset.y *= -1;\n }\n\n return `<filter id=\"SVGID_${this.id}\" y=\"-${fBoxY}%\" height=\"${\n 100 + 2 * fBoxY\n }%\" x=\"-${fBoxX}%\" width=\"${\n 100 + 2 * fBoxX\n }%\" >\\n\\t<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"${toFixed(\n this.blur ? this.blur / 2 : 0,\n config.NUM_FRACTION_DIGITS,\n )}\"></feGaussianBlur>\\n\\t<feOffset dx=\"${toFixed(\n offset.x,\n config.NUM_FRACTION_DIGITS,\n )}\" dy=\"${toFixed(\n offset.y,\n config.NUM_FRACTION_DIGITS,\n )}\" result=\"oBlur\" ></feOffset>\\n\\t<feFlood flood-color=\"${color.toRgb()}\" flood-opacity=\"${color.getAlpha()}\"/>\\n\\t<feComposite in2=\"oBlur\" operator=\"in\" />\\n\\t<feMerge>\\n\\t\\t<feMergeNode></feMergeNode>\\n\\t\\t<feMergeNode in=\"SourceGraphic\"></feMergeNode>\\n\\t</feMerge>\\n</filter>\\n`;\n }\n\n /**\n * Returns object representation of a shadow\n * @return {Object} Object representation of a shadow instance\n */\n toObject() {\n const data: SerializedShadowOptions = {\n color: this.color,\n blur: this.blur,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n affectStroke: this.affectStroke,\n nonScaling: this.nonScaling,\n type: (this.constructor as typeof Shadow).type,\n };\n const defaults = Shadow.ownDefaults as SerializedShadowOptions;\n return !this.includeDefaultValues\n ? pickBy(data, (value, key) => value !== defaults[key])\n : data;\n }\n\n static async fromObject(options: Partial<TClassProperties<Shadow>>) {\n return new this(options);\n }\n}\n\nclassRegistry.setClass(Shadow, 'shadow');\n"],"names":["shadowOffsetRegex","reOffsetsAndBlur","RegExp","reNum","shadowDefaultValues","color","blur","offsetX","offsetY","affectStroke","includeDefaultValues","nonScaling","Shadow","constructor","arg0","options","parseShadow","Object","assign","this","ownDefaults","id","uid","value","shadowStr","trim","exec","map","parseFloat","replace","toString","join","toSVG","object","offset","rotateVector","Point","degreesToRadians","angle","Color","fBoxX","fBoxY","width","height","toFixed","Math","abs","x","config","NUM_FRACTION_DIGITS","y","flipX","flipY","concat","toRgb","getAlpha","toObject","data","type","defaults","pickBy","key","fromObject","_defineProperty","classRegistry","setClass"],"mappings":"gmBA+BA,MAAMA,EAAoB,yCAEpBC,EAAmB,IAAIC,OAC3B,YACEF,EACAA,EACA,IACAG,EACA,iCAGSC,EAAyD,CACpEC,MAAO,aACPC,KAAM,EACNC,QAAS,EACTC,QAAS,EACTC,cAAc,EACdC,sBAAsB,EACtBC,YAAY,GAaP,MAAMC,EA+DXC,WAAAA,CAAYC,GACV,MAAMC,EACY,iBAATD,EAAoBF,EAAOI,YAAYF,GAAQA,EACxDG,OAAOC,OAAOC,KAAMP,EAAOQ,YAAaL,GACxCI,KAAKE,GAAKC,GACZ,CAMA,kBAAON,CAAYO,GACjB,MAAMC,EAAYD,EAAME,QACnBlB,CAAAA,EAAU,EAAGC,EAAU,EAAGF,EAAO,IAClCL,EAAiByB,KAAKF,IAAc,IACpCG,KAAKJ,GAAUK,WAAWL,IAAU,IAGxC,MAAO,CACLlB,OAHSmB,EAAUK,QAAQ5B,EAAkB,KAAO,cAAcwB,OAIlElB,UACAC,UACAF,OAEJ,CAOAwB,QAAAA,GACE,MAAO,CAACX,KAAKZ,QAASY,KAAKX,QAASW,KAAKb,KAAMa,KAAKd,OAAO0B,KAAK,MAClE,CAOAC,KAAAA,CAAMC,GACJ,MAAMC,EAASC,EACX,IAAIC,EAAMjB,KAAKZ,QAASY,KAAKX,SAC7B6B,GAAkBJ,EAAOK,QAG3BjC,EAAQ,IAAIkC,EAAMpB,KAAKd,OACzB,IAAImC,EAAQ,GACVC,EAAQ,GA2BV,OAzBIR,EAAOS,OAAST,EAAOU,SAGzBH,EAKI,IAJFI,GACGC,KAAKC,IAAIZ,EAAOa,GAAK5B,KAAKb,MAAQ2B,EAAOS,MAC1CM,EAAOC,qBAXA,GAeXR,EAKI,IAJFG,GACGC,KAAKC,IAAIZ,EAAOgB,GAAK/B,KAAKb,MAAQ2B,EAAOU,OAC1CK,EAAOC,qBAlBA,IAuBThB,EAAOkB,QACTjB,EAAOa,IAAM,GAEXd,EAAOmB,QACTlB,EAAOgB,IAAM,GAGf,qBAAAG,OAA4BlC,KAAKE,GAAE,UAAAgC,OAASZ,iBAAKY,OAC/C,IAAM,EAAIZ,EAAK,WAAAY,OACPb,gBAAKa,OACb,IAAM,EAAIb,EAAK,2DAAAa,OACyCT,EACxDzB,KAAKb,KAAOa,KAAKb,KAAO,EAAI,EAC5B0C,EAAOC,qBACR,yCAAAI,OAAwCT,EACvCV,EAAOa,EACPC,EAAOC,+BACRI,OAAST,EACRV,EAAOgB,EACPF,EAAOC,qBACRI,2DAAAA,OAA0DhD,EAAMiD,6BAAOD,OAAoBhD,EAAMkD,WAAU,gLAC9G,CAMAC,QAAAA,GACE,MAAMC,EAAgC,CACpCpD,MAAOc,KAAKd,MACZC,KAAMa,KAAKb,KACXC,QAASY,KAAKZ,QACdC,QAASW,KAAKX,QACdC,aAAcU,KAAKV,aACnBE,WAAYQ,KAAKR,WACjB+C,KAAOvC,KAAKN,YAA8B6C,MAEtCC,EAAW/C,EAAOQ,YACxB,OAAQD,KAAKT,qBAET+C,EADAG,EAAOH,GAAM,CAAClC,EAAOsC,IAAQtC,IAAUoC,EAASE,IAEtD,CAEA,uBAAaC,CAAW/C,GACtB,OAAO,IAAII,KAAKJ,EAClB,EAtIAgD,EA1CWnD,EAAM,cAqDIR,GAAmB2D,EArD7BnD,EAAM,OAuDH,UA4HhBoD,EAAcC,SAASrD,EAAQ"}