1 //= require "object.class" 2 3 (function(global) { 4 5 "use strict"; 6 7 var fabric = global.fabric || (global.fabric = { }); 8 9 if (fabric.Rect) { 10 console.warn('fabric.Rect is already defined'); 11 return; 12 } 13 14 /** 15 * @class Rect 16 * @extends fabric.Object 17 */ 18 fabric.Rect = fabric.util.createClass(fabric.Object, /** @scope fabric.Rect.prototype */ { 19 20 /** 21 * @property 22 * @type String 23 */ 24 type: 'rect', 25 26 /** 27 * @property 28 * @type Object 29 */ 30 options: { 31 rx: 0, 32 ry: 0 33 }, 34 35 /** 36 * Constructor 37 * @method initialize 38 * @param options {Object} options object 39 * @return {Object} thisArg 40 */ 41 initialize: function(options) { 42 this._initStateProperties(); 43 this.callSuper('initialize', options); 44 this._initRxRy(); 45 }, 46 47 /** 48 * Creates `stateProperties` list on an instance, and adds `fabric.Rect` -specific ones to it 49 * (such as "rx", "ry", etc.) 50 * @private 51 * @method _initStateProperties 52 */ 53 _initStateProperties: function() { 54 this.stateProperties = this.stateProperties.concat(['rx', 'ry']); 55 }, 56 57 /** 58 * @private 59 * @method _initRxRy 60 */ 61 _initRxRy: function() { 62 if (this.rx && !this.ry) { 63 this.ry = this.rx; 64 } 65 else if (this.ry && !this.rx) { 66 this.rx = this.ry; 67 } 68 }, 69 70 /** 71 * @private 72 * @method _render 73 * @param ctx {CanvasRenderingContext2D} context to render on 74 */ 75 _render: function(ctx) { 76 var rx = this.rx || 0, 77 ry = this.ry || 0, 78 x = -this.width / 2, 79 y = -this.height / 2, 80 w = this.width, 81 h = this.height; 82 83 ctx.beginPath(); 84 ctx.globalAlpha *= this.opacity; 85 86 ctx.moveTo(x+rx, y); 87 ctx.lineTo(x+w-rx, y); 88 ctx.bezierCurveTo(x+w, y, x+w, y+ry, x+w, y+ry); 89 ctx.lineTo(x+w, y+h-ry); 90 ctx.bezierCurveTo(x+w,y+h,x+w-rx,y+h,x+w-rx,y+h); 91 ctx.lineTo(x+rx,y+h); 92 ctx.bezierCurveTo(x,y+h,x,y+h-ry,x,y+h-ry); 93 ctx.lineTo(x,y+ry); 94 ctx.bezierCurveTo(x,y,x+rx,y,x+rx,y); 95 ctx.closePath(); 96 97 if (this.fill) { 98 ctx.fill(); 99 } 100 if (this.stroke) { 101 ctx.stroke(); 102 } 103 }, 104 105 // since our coordinate system differs from that of SVG 106 _normalizeLeftTopProperties: function(parsedAttributes) { 107 if (parsedAttributes.left) { 108 this.set('left', parsedAttributes.left + this.getWidth() / 2); 109 } 110 if (parsedAttributes.top) { 111 this.set('top', parsedAttributes.top + this.getHeight() / 2); 112 } 113 return this; 114 }, 115 116 /** 117 * @method complexity 118 * @return {Number} complexity 119 */ 120 complexity: function() { 121 return 1; 122 } 123 }); 124 125 // TODO (kangax): implement rounded rectangles (both parsing and rendering) 126 127 /** 128 * List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`) 129 * @static 130 */ 131 fabric.Rect.ATTRIBUTE_NAMES = 'x y width height rx ry fill fill-opacity opacity stroke stroke-width transform'.split(' '); 132 133 /** 134 * @private 135 */ 136 function _setDefaultLeftTopValues(attributes) { 137 attributes.left = attributes.left || 0; 138 attributes.top = attributes.top || 0; 139 return attributes; 140 } 141 142 /** 143 * Returns fabric.Rect instance from an SVG element 144 * @static 145 * @method fabric.Rect.fromElement 146 * @param element {SVGElement} element to parse 147 * @param options {Object} options object 148 * @return {fabric.Rect} instance of fabric.Rect 149 */ 150 fabric.Rect.fromElement = function(element, options) { 151 if (!element) { 152 return null; 153 } 154 155 var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES); 156 parsedAttributes = _setDefaultLeftTopValues(parsedAttributes); 157 158 var rect = new fabric.Rect(fabric.util.object.extend((options ? fabric.util.object.clone(options) : { }), parsedAttributes)); 159 rect._normalizeLeftTopProperties(parsedAttributes); 160 161 return rect; 162 }; 163 164 /** 165 * Returns fabric.Rect instance from an object representation 166 * @static 167 * @method fabric.Rect.fromObject 168 * @param object {Object} object to create an instance from 169 * @return {Object} instance of fabric.Rect 170 */ 171 fabric.Rect.fromObject = function(object) { 172 return new fabric.Rect(object); 173 }; 174 })(this);