UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

1 lines 18.4 kB
{"version":3,"file":"Control.mjs","sources":["../../../src/controls/Control.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type {\n ControlActionHandler,\n TPointerEvent,\n TransformActionHandler,\n} from '../EventTypeDefs';\nimport { Intersection } from '../Intersection';\nimport { Point } from '../Point';\nimport { SCALE } from '../constants';\nimport type { InteractiveFabricObject } from '../shapes/Object/InteractiveObject';\nimport type { TCornerPoint, TDegree, TMat2D } from '../typedefs';\nimport {\n createRotateMatrix,\n createScaleMatrix,\n createTranslateMatrix,\n multiplyTransformMatrixArray,\n} from '../util/misc/matrix';\nimport type { ControlRenderingStyleOverride } from './controlRendering';\nimport { renderCircleControl, renderSquareControl } from './controlRendering';\n\nexport class Control {\n /**\n * keep track of control visibility.\n * mainly for backward compatibility.\n * if you do not want to see a control, you can remove it\n * from the control set.\n * @type {Boolean}\n * @default true\n */\n visible = true;\n\n /**\n * Name of the action that the control will likely execute.\n * This is optional. FabricJS uses to identify what the user is doing for some\n * extra optimizations. If you are writing a custom control and you want to know\n * somewhere else in the code what is going on, you can use this string here.\n * you can also provide a custom getActionName if your control run multiple actions\n * depending on some external state.\n * default to scale since is the most common, used on 4 corners by default\n * @type {String}\n * @default 'scale'\n */\n actionName = SCALE;\n\n /**\n * Drawing angle of the control.\n * NOT used for now, but name marked as needed for internal logic\n * example: to reuse the same drawing function for different rotated controls\n * @type {Number}\n * @default 0\n */\n angle = 0;\n\n /**\n * Relative position of the control. X\n * 0,0 is the center of the Object, while -0.5 (left) or 0.5 (right) are the extremities\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n x = 0;\n\n /**\n * Relative position of the control. Y\n * 0,0 is the center of the Object, while -0.5 (top) or 0.5 (bottom) are the extremities\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n y = 0;\n\n /**\n * Horizontal offset of the control from the defined position. In pixels\n * Positive offset moves the control to the right, negative to the left.\n * It used when you want to have position of control that does not scale with\n * the bounding box. Example: rotation control is placed at x:0, y: 0.5 on\n * the boundind box, with an offset of 30 pixels vertically. Those 30 pixels will\n * stay 30 pixels no matter how the object is big. Another example is having 2\n * controls in the corner, that stay in the same position when the object scale.\n * of the bounding box.\n * @type {Number}\n * @default 0\n */\n offsetX = 0;\n\n /**\n * Vertical offset of the control from the defined position. In pixels\n * Positive offset moves the control to the bottom, negative to the top.\n * @type {Number}\n * @default 0\n */\n offsetY = 0;\n\n /**\n * Sets the length of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeX = 0;\n\n /**\n * Sets the height of the control. If null, defaults to object's cornerSize.\n * Expects both sizeX and sizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n sizeY = 0;\n\n /**\n * Sets the length of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeX = 0;\n\n /**\n * Sets the height of the touch area of the control. If null, defaults to object's touchCornerSize.\n * Expects both touchSizeX and touchSizeY to be set when set.\n * @type {?Number}\n * @default null\n */\n touchSizeY = 0;\n\n /**\n * Css cursor style to display when the control is hovered.\n * if the method `cursorStyleHandler` is provided, this property is ignored.\n * @type {String}\n * @default 'crosshair'\n */\n cursorStyle = 'crosshair';\n\n /**\n * If controls has an offsetY or offsetX, draw a line that connects\n * the control to the bounding box\n * @type {Boolean}\n * @default false\n */\n withConnection = false;\n\n constructor(options?: Partial<Control>) {\n Object.assign(this, options);\n }\n\n /**\n * The control actionHandler, provide one to handle action ( control being moved )\n * @param {Event} eventData the native mouse event\n * @param {Transform} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n declare actionHandler: TransformActionHandler;\n\n /**\n * The control handler for mouse down, provide one to handle mouse down on control\n * @param {Event} eventData the native mouse event\n * @param {Transform} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n declare mouseDownHandler?: ControlActionHandler;\n\n /**\n * The control mouseUpHandler, provide one to handle an effect on mouse up.\n * @param {Event} eventData the native mouse event\n * @param {Transform} transformData properties of the current transform\n * @param {Number} x x position of the cursor\n * @param {Number} y y position of the cursor\n * @return {Boolean} true if the action/event modified the object\n */\n declare mouseUpHandler?: ControlActionHandler;\n\n shouldActivate(\n controlKey: string,\n fabricObject: InteractiveFabricObject,\n pointer: Point,\n { tl, tr, br, bl }: TCornerPoint,\n ) {\n // TODO: locking logic can be handled here instead of in the control handler logic\n return (\n fabricObject.canvas?.getActiveObject() === fabricObject &&\n fabricObject.isControlVisible(controlKey) &&\n Intersection.isPointInPolygon(pointer, [tl, tr, br, bl])\n );\n }\n\n /**\n * Returns control actionHandler\n * @param {Event} eventData the native mouse event\n * @param {FabricObject} fabricObject on which the control is displayed\n * @param {Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getActionHandler(\n eventData: TPointerEvent,\n fabricObject: InteractiveFabricObject,\n control: Control,\n ): TransformActionHandler | undefined {\n return this.actionHandler;\n }\n\n /**\n * Returns control mouseDown handler\n * @param {Event} eventData the native mouse event\n * @param {FabricObject} fabricObject on which the control is displayed\n * @param {Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getMouseDownHandler(\n eventData: TPointerEvent,\n fabricObject: InteractiveFabricObject,\n control: Control,\n ): ControlActionHandler | undefined {\n return this.mouseDownHandler;\n }\n\n /**\n * Returns control mouseUp handler.\n * During actions the fabricObject or the control can be of different obj\n * @param {Event} eventData the native mouse event\n * @param {FabricObject} fabricObject on which the control is displayed\n * @param {Control} control control for which the action handler is being asked\n * @return {Function} the action handler\n */\n getMouseUpHandler(\n eventData: TPointerEvent,\n fabricObject: InteractiveFabricObject,\n control: Control,\n ): ControlActionHandler | undefined {\n return this.mouseUpHandler;\n }\n\n /**\n * Returns control cursorStyle for css using cursorStyle. If you need a more elaborate\n * function you can pass one in the constructor\n * the cursorStyle property\n * @param {Event} eventData the native mouse event\n * @param {Control} control the current control ( likely this)\n * @param {FabricObject} object on which the control is displayed\n * @return {String}\n */\n cursorStyleHandler(\n eventData: TPointerEvent,\n control: Control,\n fabricObject: InteractiveFabricObject,\n ) {\n return control.cursorStyle;\n }\n\n /**\n * Returns the action name. The basic implementation just return the actionName property.\n * @param {Event} eventData the native mouse event\n * @param {Control} control the current control ( likely this)\n * @param {FabricObject} object on which the control is displayed\n * @return {String}\n */\n getActionName(\n eventData: TPointerEvent,\n control: Control,\n fabricObject: InteractiveFabricObject,\n ) {\n return control.actionName;\n }\n\n /**\n * Returns controls visibility\n * @param {FabricObject} object on which the control is displayed\n * @param {String} controlKey key where the control is memorized on the\n * @return {Boolean}\n */\n getVisibility(fabricObject: InteractiveFabricObject, controlKey: string) {\n return fabricObject._controlsVisibility?.[controlKey] ?? this.visible;\n }\n\n /**\n * Sets controls visibility\n * @param {Boolean} visibility for the object\n * @return {Void}\n */\n setVisibility(\n visibility: boolean,\n name: string,\n fabricObject: InteractiveFabricObject,\n ) {\n this.visible = visibility;\n }\n\n positionHandler(\n dim: Point,\n finalMatrix: TMat2D,\n fabricObject: InteractiveFabricObject,\n currentControl: Control,\n ) {\n return new Point(\n this.x * dim.x + this.offsetX,\n this.y * dim.y + this.offsetY,\n ).transform(finalMatrix);\n }\n\n /**\n * Returns the coords for this control based on object values.\n * @param {Number} objectAngle angle from the fabric object holding the control\n * @param {Number} objectCornerSize cornerSize from the fabric object holding the control (or touchCornerSize if\n * isTouch is true)\n * @param {Number} centerX x coordinate where the control center should be\n * @param {Number} centerY y coordinate where the control center should be\n * @param {boolean} isTouch true if touch corner, false if normal corner\n */\n calcCornerCoords(\n angle: TDegree,\n objectCornerSize: number,\n centerX: number,\n centerY: number,\n isTouch: boolean,\n fabricObject: InteractiveFabricObject,\n ) {\n const t = multiplyTransformMatrixArray([\n createTranslateMatrix(centerX, centerY),\n createRotateMatrix({ angle }),\n createScaleMatrix(\n (isTouch ? this.touchSizeX : this.sizeX) || objectCornerSize,\n (isTouch ? this.touchSizeY : this.sizeY) || objectCornerSize,\n ),\n ]);\n return {\n tl: new Point(-0.5, -0.5).transform(t),\n tr: new Point(0.5, -0.5).transform(t),\n br: new Point(0.5, 0.5).transform(t),\n bl: new Point(-0.5, 0.5).transform(t),\n };\n }\n\n /**\n * Render function for the control.\n * When this function runs the context is unscaled. unrotate. Just retina scaled.\n * all the functions will have to translate to the point left,top before starting Drawing\n * if they want to draw a control where the position is detected.\n * left and top are the result of the positionHandler function\n * @param {RenderingContext2D} ctx the context where the control will be drawn\n * @param {Number} left position of the canvas where we are about to render the control.\n * @param {Number} top position of the canvas where we are about to render the control.\n * @param {Object} styleOverride\n * @param {FabricObject} fabricObject the object where the control is about to be rendered\n */\n render(\n ctx: CanvasRenderingContext2D,\n left: number,\n top: number,\n styleOverride: ControlRenderingStyleOverride | undefined,\n fabricObject: InteractiveFabricObject,\n ) {\n styleOverride = styleOverride || {};\n switch (styleOverride.cornerStyle || fabricObject.cornerStyle) {\n case 'circle':\n renderCircleControl.call(\n this,\n ctx,\n left,\n top,\n styleOverride,\n fabricObject,\n );\n break;\n default:\n renderSquareControl.call(\n this,\n ctx,\n left,\n top,\n styleOverride,\n fabricObject,\n );\n }\n }\n}\n"],"names":["Control","constructor","options","_defineProperty","SCALE","Object","assign","shouldActivate","controlKey","fabricObject","pointer","_ref","_fabricObject$canvas","tl","tr","br","bl","canvas","getActiveObject","isControlVisible","Intersection","isPointInPolygon","getActionHandler","eventData","control","actionHandler","getMouseDownHandler","mouseDownHandler","getMouseUpHandler","mouseUpHandler","cursorStyleHandler","cursorStyle","getActionName","actionName","getVisibility","_fabricObject$_contro","_fabricObject$_contro2","_controlsVisibility","visible","setVisibility","visibility","name","positionHandler","dim","finalMatrix","currentControl","Point","x","offsetX","y","offsetY","transform","calcCornerCoords","angle","objectCornerSize","centerX","centerY","isTouch","t","multiplyTransformMatrixArray","createTranslateMatrix","createRotateMatrix","createScaleMatrix","touchSizeX","sizeX","touchSizeY","sizeY","render","ctx","left","top","styleOverride","cornerStyle","renderCircleControl","call","renderSquareControl"],"mappings":";;;;;;;AAoBO,MAAMA,OAAO,CAAC;EAyHnBC,WAAWA,CAACC,OAA0B,EAAE;AAxHxC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AAPEC,IAAAA,eAAA,kBAQU,IAAI,CAAA,CAAA;AAEd;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAVEA,IAAAA,eAAA,qBAWaC,KAAK,CAAA,CAAA;AAElB;AACF;AACA;AACA;AACA;AACA;AACA;AANED,IAAAA,eAAA,gBAOQ,CAAC,CAAA,CAAA;AAET;AACF;AACA;AACA;AACA;AACA;AACA;AANEA,IAAAA,eAAA,YAOI,CAAC,CAAA,CAAA;AAEL;AACF;AACA;AACA;AACA;AACA;AACA;AANEA,IAAAA,eAAA,YAOI,CAAC,CAAA,CAAA;AAEL;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAXEA,IAAAA,eAAA,kBAYU,CAAC,CAAA,CAAA;AAEX;AACF;AACA;AACA;AACA;AACA;AALEA,IAAAA,eAAA,kBAMU,CAAC,CAAA,CAAA;AAEX;AACF;AACA;AACA;AACA;AACA;AALEA,IAAAA,eAAA,gBAMQ,CAAC,CAAA,CAAA;AAET;AACF;AACA;AACA;AACA;AACA;AALEA,IAAAA,eAAA,gBAMQ,CAAC,CAAA,CAAA;AAET;AACF;AACA;AACA;AACA;AACA;AALEA,IAAAA,eAAA,qBAMa,CAAC,CAAA,CAAA;AAEd;AACF;AACA;AACA;AACA;AACA;AALEA,IAAAA,eAAA,qBAMa,CAAC,CAAA,CAAA;AAEd;AACF;AACA;AACA;AACA;AACA;AALEA,IAAAA,eAAA,sBAMc,WAAW,CAAA,CAAA;AAEzB;AACF;AACA;AACA;AACA;AACA;AALEA,IAAAA,eAAA,yBAMiB,KAAK,CAAA,CAAA;AAGpBE,IAAAA,MAAM,CAACC,MAAM,CAAC,IAAI,EAAEJ,OAAO,CAAC,CAAA;AAC9B,GAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;AAGE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;AAGE;AACF;AACA;AAC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"}