fabric.js/src/shapes/rect.class.js
neopheus 3544b727be Update code v2 (#3180)
* update JSDOC - v4
* update JSDOC -v5
2016-08-20 17:58:16 +02:00

242 lines
6.9 KiB
JavaScript

(function(global) {
'use strict';
var fabric = global.fabric || (global.fabric = { }),
extend = fabric.util.object.extend;
if (fabric.Rect) {
fabric.warn('fabric.Rect is already defined');
return;
}
var stateProperties = fabric.Object.prototype.stateProperties.concat();
stateProperties.push('rx', 'ry', 'x', 'y');
/**
* Rectangle class
* @class fabric.Rect
* @extends fabric.Object
* @return {fabric.Rect} thisArg
* @see {@link fabric.Rect#initialize} for constructor definition
*/
fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {
/**
* List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
* as well as for history (undo/redo) purposes
* @type Array
*/
stateProperties: stateProperties,
/**
* Type of an object
* @type String
* @default
*/
type: 'rect',
/**
* Horizontal border radius
* @type Number
* @default
*/
rx: 0,
/**
* Vertical border radius
* @type Number
* @default
*/
ry: 0,
/**
* Used to specify dash pattern for stroke on this object
* @type Array
*/
strokeDashArray: null,
/**
* Constructor
* @param {Object} [options] Options object
* @return {Object} thisArg
*/
initialize: function(options) {
options = options || { };
this.callSuper('initialize', options);
this._initRxRy();
},
/**
* Initializes rx/ry attributes
* @private
*/
_initRxRy: function() {
if (this.rx && !this.ry) {
this.ry = this.rx;
}
else if (this.ry && !this.rx) {
this.rx = this.ry;
}
},
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} noTransform
*/
_render: function(ctx, noTransform) {
// optimize 1x1 case (used in spray brush)
if (this.width === 1 && this.height === 1) {
ctx.fillRect(-0.5, -0.5, 1, 1);
return;
}
var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,
ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,
w = this.width,
h = this.height,
x = noTransform ? this.left : -this.width / 2,
y = noTransform ? this.top : -this.height / 2,
isRounded = rx !== 0 || ry !== 0,
k = 1 - 0.5522847498 /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */;
ctx.beginPath();
ctx.moveTo(x + rx, y);
ctx.lineTo(x + w - rx, y);
isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);
ctx.lineTo(x + w, y + h - ry);
isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);
ctx.lineTo(x + rx, y + h);
isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);
ctx.lineTo(x, y + ry);
isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);
ctx.closePath();
this._renderFill(ctx);
this._renderStroke(ctx);
},
/**
* @private
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
_renderDashedStroke: function(ctx) {
var x = -this.width / 2,
y = -this.height / 2,
w = this.width,
h = this.height;
ctx.beginPath();
fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);
fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);
fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);
fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);
ctx.closePath();
},
/**
* Returns object representation of an instance
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
* @return {Object} object representation of an instance
*/
toObject: function(propertiesToInclude) {
var object = extend(this.callSuper('toObject', propertiesToInclude), {
rx: this.get('rx') || 0,
ry: this.get('ry') || 0
});
if (!this.includeDefaultValues) {
this._removeDefaultValues(object);
}
return object;
},
/* _TO_SVG_START_ */
/**
* Returns svg representation of an instance
* @param {Function} [reviver] Method for further parsing of svg representation.
* @return {String} svg representation of an instance
*/
toSVG: function(reviver) {
var markup = this._createBaseSVGMarkup(), x = this.left, y = this.top;
if (!(this.group && this.group.type === 'path-group')) {
x = -this.width / 2;
y = -this.height / 2;
}
markup.push(
'<rect ', this.getSvgId(),
'x="', x, '" y="', y,
'" rx="', this.get('rx'), '" ry="', this.get('ry'),
'" width="', this.width, '" height="', this.height,
'" style="', this.getSvgStyles(),
'" transform="', this.getSvgTransform(),
this.getSvgTransformMatrix(),
'"/>\n');
return reviver ? reviver(markup.join('')) : markup.join('');
},
/* _TO_SVG_END_ */
/**
* Returns complexity of an instance
* @return {Number} complexity
*/
complexity: function() {
return 1;
}
});
/* _FROM_SVG_START_ */
/**
* List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)
* @static
* @memberOf fabric.Rect
* @see: http://www.w3.org/TR/SVG/shapes.html#RectElement
*/
fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));
/**
* Returns {@link fabric.Rect} instance from an SVG element
* @static
* @memberOf fabric.Rect
* @param {SVGElement} element Element to parse
* @param {Object} [options] Options object
* @return {fabric.Rect} Instance of fabric.Rect
*/
fabric.Rect.fromElement = function(element, options) {
if (!element) {
return null;
}
options = options || { };
var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);
parsedAttributes.left = parsedAttributes.left || 0;
parsedAttributes.top = parsedAttributes.top || 0;
var rect = new fabric.Rect(extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes));
rect.visible = rect.visible && rect.width > 0 && rect.height > 0;
return rect;
};
/* _FROM_SVG_END_ */
/**
* Returns {@link fabric.Rect} instance from an object representation
* @static
* @memberOf fabric.Rect
* @param {Object} object Object to create an instance from
* @return {Object} instance of fabric.Rect
*/
fabric.Rect.fromObject = function(object) {
return new fabric.Rect(object);
};
})(typeof exports !== 'undefined' ? exports : this);