1 //= require "object.class" 2 3 (function(global){ 4 5 "use strict"; 6 7 var fabric = global.fabric || (global.fabric = { }), 8 piBy2 = Math.PI * 2, 9 extend = fabric.util.object.extend; 10 11 if (fabric.Ellipse) { 12 fabric.warn('fabric.Ellipse is already defined.'); 13 return; 14 } 15 16 /** 17 * @class Ellipse 18 * @extends fabric.Object 19 */ 20 fabric.Ellipse = fabric.util.createClass(fabric.Object, /** @scope fabric.Ellipse.prototype */ { 21 22 /** 23 * @property 24 * @type String 25 */ 26 type: 'ellipse', 27 28 /** 29 * Constructor 30 * @method initialize 31 * @param {Object} [options] Options object 32 * @return {Object} thisArg 33 */ 34 initialize: function(options) { 35 options = options || { }; 36 37 this.callSuper('initialize', options); 38 39 this.set('rx', options.rx || 0); 40 this.set('ry', options.ry || 0); 41 42 this.set('width', this.get('rx') * 2); 43 this.set('height', this.get('ry') * 2); 44 }, 45 46 /** 47 * Returns object representation of an instance 48 * @method toObject 49 * @return {Object} object representation of an instance 50 */ 51 toObject: function() { 52 return extend(this.callSuper('toObject'), { 53 rx: this.get('rx'), 54 ry: this.get('ry') 55 }); 56 }, 57 58 /** 59 * Renders this instance on a given context 60 * @method render 61 * @param ctx {CanvasRenderingContext2D} context to render on 62 * @param noTransform {Boolean} context is not transformed when set to true 63 */ 64 render: function(ctx, noTransform) { 65 // do not use `get` for perf. reasons 66 if (this.rx === 0 || this.ry === 0) return; 67 return this.callSuper('render', ctx, noTransform); 68 }, 69 70 /** 71 * @private 72 * @method _render 73 * @param ctx {CanvasRenderingContext2D} context to render on 74 */ 75 _render: function(ctx, noTransform) { 76 ctx.beginPath(); 77 ctx.save(); 78 ctx.globalAlpha *= this.opacity; 79 ctx.transform(1, 0, 0, this.ry/this.rx, 0, 0); 80 ctx.arc(noTransform ? this.left : 0, noTransform ? this.top : 0, this.rx, 0, piBy2, false); 81 if (this.stroke) { 82 ctx.stroke(); 83 } 84 if (this.fill) { 85 ctx.fill(); 86 } 87 ctx.restore(); 88 }, 89 90 /** 91 * Returns complexity of an instance 92 * @method complexity 93 * @return {Number} complexity 94 */ 95 complexity: function() { 96 return 1; 97 } 98 }); 99 100 /** 101 * List of attribute names to account for when parsing SVG element (used by {@link fabric.Ellipse.fromElement}) 102 * @static 103 * @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement 104 */ 105 fabric.Ellipse.ATTRIBUTE_NAMES = 'cx cy rx ry fill fill-opacity opacity stroke stroke-width transform'.split(' '); 106 107 /** 108 * Returns {@link fabric.Ellipse} instance from an SVG element 109 * @static 110 * @method fabric.Ellipse.fromElement 111 * @param {SVGElement} element Element to parse 112 * @param {Object} [options] Options object 113 * @return {fabric.Ellipse} 114 */ 115 fabric.Ellipse.fromElement = function(element, options) { 116 options || (options = { }); 117 var parsedAttributes = fabric.parseAttributes(element, fabric.Ellipse.ATTRIBUTE_NAMES); 118 if ('left' in parsedAttributes) { 119 parsedAttributes.left -= (options.width / 2) || 0; 120 } 121 if ('top' in parsedAttributes) { 122 parsedAttributes.top -= (options.height / 2) || 0; 123 } 124 return new fabric.Ellipse(extend(parsedAttributes, options)); 125 }; 126 127 /** 128 * Returns fabric.Ellipse instance from an object representation 129 * @static 130 * @method fabric.Ellipse.fromObject 131 * @param {Object} object Object to create an instance from 132 * @return {fabric.Ellipse} 133 */ 134 fabric.Ellipse.fromObject = function(object) { 135 return new fabric.Ellipse(object); 136 } 137 })(this);