fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 17.5 kB
Source Map (JSON)
{"version":3,"file":"scale.mjs","sources":["../../../src/controls/scale.ts"],"sourcesContent":["import type {\n ControlCursorCallback,\n TPointerEvent,\n Transform,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport type { TAxis } from '../typedefs';\nimport type { Canvas } from '../canvas/Canvas';\nimport {\n findCornerQuadrant,\n getLocalPoint,\n invertOrigin,\n isLocked,\n isTransformCentered,\n NOT_ALLOWED_CURSOR,\n} from './util';\nimport { wrapWithFireEvent } from './wrapWithFireEvent';\nimport { wrapWithFixedAnchor } from './wrapWithFixedAnchor';\nimport { SCALE_X, SCALE_Y, SCALING } from '../constants';\n\ntype ScaleTransform = Transform & {\n gestureScale?: number;\n signX?: number;\n signY?: number;\n};\n\ntype ScaleBy = TAxis | 'equally' | '' | undefined;\n\n/**\n * Inspect event and fabricObject properties to understand if the scaling action\n * @param {Event} eventData from the user action\n * @param {FabricObject} fabricObject the fabric object about to scale\n * @return {Boolean} true if scale is proportional\n */\nexport function scaleIsProportional(\n eventData: TPointerEvent,\n fabricObject: FabricObject,\n): boolean {\n const canvas = fabricObject.canvas as Canvas,\n uniformIsToggled = eventData[canvas.uniScaleKey!];\n return (\n (canvas.uniformScaling && !uniformIsToggled) ||\n (!canvas.uniformScaling && uniformIsToggled)\n );\n}\n\n/**\n * Inspect fabricObject to understand if the current scaling action is allowed\n * @param {FabricObject} fabricObject the fabric object about to scale\n * @param {String} by 'x' or 'y' or ''\n * @param {Boolean} scaleProportionally true if we are trying to scale proportionally\n * @return {Boolean} true if scaling is not allowed at current conditions\n */\nexport function scalingIsForbidden(\n fabricObject: FabricObject,\n by: ScaleBy,\n scaleProportionally: boolean,\n) {\n const lockX = isLocked(fabricObject, 'lockScalingX'),\n lockY = isLocked(fabricObject, 'lockScalingY');\n if (lockX && lockY) {\n return true;\n }\n if (!by && (lockX || lockY) && scaleProportionally) {\n return true;\n }\n if (lockX && by === 'x') {\n return true;\n }\n if (lockY && by === 'y') {\n return true;\n }\n // code crashes because of a division by 0 if a 0 sized object is scaled\n // forbid to prevent scaling to happen. ISSUE-9475\n const { width, height, strokeWidth } = fabricObject;\n if (width === 0 && strokeWidth === 0 && by !== 'y') {\n return true;\n }\n if (height === 0 && strokeWidth === 0 && by !== 'x') {\n return true;\n }\n return false;\n}\n\nconst scaleMap = ['e', 'se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'];\n\n/**\n * return the correct cursor style for the scale action\n * @param {Event} eventData the javascript event that is causing the scale\n * @param {Control} control the control that is interested in the action\n * @param {FabricObject} fabricObject the fabric object that is interested in the action\n * @return {String} a valid css string for the cursor\n */\nexport const scaleCursorStyleHandler: ControlCursorCallback = (\n eventData,\n control,\n fabricObject,\n) => {\n const scaleProportionally = scaleIsProportional(eventData, fabricObject),\n by =\n control.x !== 0 && control.y === 0\n ? 'x'\n : control.x === 0 && control.y !== 0\n ? 'y'\n : '';\n if (scalingIsForbidden(fabricObject, by, scaleProportionally)) {\n return NOT_ALLOWED_CURSOR;\n }\n const n = findCornerQuadrant(fabricObject, control);\n return `${scaleMap[n]}-resize`;\n};\n\n/**\n * Basic scaling logic, reused with different constrain for scaling X,Y, freely or equally.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @param {Object} options additional information for scaling\n * @param {String} options.by 'x', 'y', 'equally' or '' to indicate type of scaling\n * @return {Boolean} true if some change happened\n * @private\n */\nfunction scaleObject(\n eventData: TPointerEvent,\n transform: ScaleTransform,\n x: number,\n y: number,\n options: { by?: ScaleBy } = {},\n) {\n const target = transform.target,\n by = options.by,\n scaleProportionally = scaleIsProportional(eventData, target),\n forbidScaling = scalingIsForbidden(target, by, scaleProportionally);\n let newPoint, scaleX, scaleY, dim, signX, signY;\n\n if (forbidScaling) {\n return false;\n }\n if (transform.gestureScale) {\n scaleX = transform.scaleX * transform.gestureScale;\n scaleY = transform.scaleY * transform.gestureScale;\n } else {\n newPoint = getLocalPoint(\n transform,\n transform.originX,\n transform.originY,\n x,\n y,\n );\n // use of sign: We use sign to detect change of direction of an action. sign usually change when\n // we cross the origin point with the mouse. So a scale flip for example. There is an issue when scaling\n // by center and scaling using one middle control ( default: mr, mt, ml, mb), the mouse movement can easily\n // cross many time the origin point and flip the object. so we need a way to filter out the noise.\n // This ternary here should be ok to filter out X scaling when we want Y only and vice versa.\n signX = by !== 'y' ? Math.sign(newPoint.x || transform.signX || 1) : 1;\n signY = by !== 'x' ? Math.sign(newPoint.y || transform.signY || 1) : 1;\n if (!transform.signX) {\n transform.signX = signX;\n }\n if (!transform.signY) {\n transform.signY = signY;\n }\n\n if (\n isLocked(target, 'lockScalingFlip') &&\n (transform.signX !== signX || transform.signY !== signY)\n ) {\n return false;\n }\n\n dim = target._getTransformedDimensions();\n // missing detection of flip and logic to switch the origin\n if (scaleProportionally && !by) {\n // uniform scaling\n const distance = Math.abs(newPoint.x) + Math.abs(newPoint.y),\n { original } = transform,\n originalDistance =\n Math.abs((dim.x * original.scaleX) / target.scaleX) +\n Math.abs((dim.y * original.scaleY) / target.scaleY),\n scale = distance / originalDistance;\n scaleX = original.scaleX * scale;\n scaleY = original.scaleY * scale;\n } else {\n scaleX = Math.abs((newPoint.x * target.scaleX) / dim.x);\n scaleY = Math.abs((newPoint.y * target.scaleY) / dim.y);\n }\n // if we are scaling by center, we need to double the scale\n if (isTransformCentered(transform)) {\n scaleX *= 2;\n scaleY *= 2;\n }\n if (transform.signX !== signX && by !== 'y') {\n transform.originX = invertOrigin(transform.originX);\n scaleX *= -1;\n transform.signX = signX;\n }\n if (transform.signY !== signY && by !== 'x') {\n transform.originY = invertOrigin(transform.originY);\n scaleY *= -1;\n transform.signY = signY;\n }\n }\n // minScale is taken care of in the setter.\n const oldScaleX = target.scaleX,\n oldScaleY = target.scaleY;\n if (!by) {\n !isLocked(target, 'lockScalingX') && target.set(SCALE_X, scaleX);\n !isLocked(target, 'lockScalingY') && target.set(SCALE_Y, scaleY);\n } else {\n // forbidden cases already handled on top here.\n by === 'x' && target.set(SCALE_X, scaleX);\n by === 'y' && target.set(SCALE_Y, scaleY);\n }\n return oldScaleX !== target.scaleX || oldScaleY !== target.scaleY;\n}\n\n/**\n * Generic scaling logic, to scale from corners either equally or freely.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nexport const scaleObjectFromCorner: TransformActionHandler<ScaleTransform> = (\n eventData,\n transform,\n x,\n y,\n) => {\n return scaleObject(eventData, transform, x, y);\n};\n\n/**\n * Scaling logic for the X axis.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nconst scaleObjectX: TransformActionHandler<ScaleTransform> = (\n eventData,\n transform,\n x,\n y,\n) => {\n return scaleObject(eventData, transform, x, y, { by: 'x' });\n};\n\n/**\n * Scaling logic for the Y axis.\n * Needs to be wrapped with `wrapWithFixedAnchor` to be effective\n * @param {Event} eventData javascript event that is doing the transform\n * @param {Object} transform javascript object containing a series of information around the current transform\n * @param {number} x current mouse x position, canvas normalized\n * @param {number} y current mouse y position, canvas normalized\n * @return {Boolean} true if some change happened\n */\nconst scaleObjectY: TransformActionHandler<ScaleTransform> = (\n eventData,\n transform,\n x,\n y,\n) => {\n return scaleObject(eventData, transform, x, y, { by: 'y' });\n};\n\nexport const scalingEqually = wrapWithFireEvent(\n SCALING,\n wrapWithFixedAnchor(scaleObjectFromCorner),\n);\n\nexport const scalingX = wrapWithFireEvent(\n SCALING,\n wrapWithFixedAnchor(scaleObjectX),\n);\n\nexport const scalingY = wrapWithFireEvent(\n SCALING,\n wrapWithFixedAnchor(scaleObjectY),\n);\n"],"names":["scaleIsProportional","eventData","fabricObject","canvas","uniformIsToggled","uniScaleKey","uniformScaling","scalingIsForbidden","by","scaleProportionally","lockX","isLocked","lockY","width","height","strokeWidth","scaleMap","scaleCursorStyleHandler","control","x","y","NOT_ALLOWED_CURSOR","n","findCornerQuadrant","concat","scaleObject","transform","options","arguments","length","undefined","target","forbidScaling","newPoint","scaleX","scaleY","dim","signX","signY","gestureScale","getLocalPoint","originX","originY","Math","sign","_getTransformedDimensions","distance","abs","original","originalDistance","scale","isTransformCentered","invertOrigin","oldScaleX","oldScaleY","set","SCALE_X","SCALE_Y","scaleObjectFromCorner","scaleObjectX","scaleObjectY","scalingEqually","wrapWithFireEvent","SCALING","wrapWithFixedAnchor","scalingX","scalingY"],"mappings":"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"}