1 goog.provide('lime.fill.LinearGradient'); 2 3 goog.require('lime.fill.Fill'); 4 5 /** 6 * Linear gradient fill. 7 * @constructor 8 * @extends lime.fill.Fill 9 */ 10 lime.fill.LinearGradient = function() { 11 lime.fill.Fill.call(this); 12 13 this.colors_ = []; 14 this.setDirection(0, 0, 0, 1); 15 16 }; 17 goog.inherits(lime.fill.LinearGradient, lime.fill.Fill); 18 19 /** 20 * Common name for Lineargradient objects 21 * @type {string} 22 */ 23 lime.fill.LinearGradient.prototype.id = 'lineargradient'; 24 25 /** 26 * @inheritDoc 27 */ 28 lime.fill.LinearGradient.prototype.initForSprite = function(sprite) { 29 // no CSS3 gradients in Opera yet and IE filters aren't good solution 30 if(goog.userAgent.OPERA || goog.userAgent.IE){ 31 sprite.setRenderer(lime.Renderer.CANVAS); 32 } 33 }; 34 35 /** 36 * Set direction of the gradient by defining start and endpoint 37 * locations as vectors from top-left corner to bottom-right. 38 * @param {number} x0 Start position x coordinate. 39 * @param {number} y0 Start position y coordinate. 40 * @param {number} x1 End position x coordinate. 41 * @param {number} y1 End position y coordinate. 42 * @return {lime.fill.LinearGradient} object itself. 43 */ 44 lime.fill.LinearGradient.prototype.setDirection = function(x0, y0, x1, y1) { 45 this.points_ = [x0, y0, x1, y1]; 46 47 return this; 48 }; 49 50 /** 51 * Add color stop to the gradient. Accepts same format as node.setFill(). 52 * @param {number} offset Position of color [0-1]. 53 * @param {*} color Color value. 54 * @return {lime.fill.LinearGradient} object itself. 55 */ 56 lime.fill.LinearGradient.prototype.addColorStop = function(offset, color) { 57 var color_vars = goog.array.toArray(arguments); 58 color_vars.shift(); 59 this.colors_.push([offset, lime.fill.parse(color_vars)]); 60 return this; 61 }; 62 63 /** 64 * Format color stop string for current browser 65 * @private 66 * @param {Array.<number|lime.fill.Fill>} clr Color in format [offset,color]. 67 * @return {string} Color stop CSS string. 68 */ 69 lime.fill.LinearGradient.prototype.formatColorStop_ = function(clr) { 70 71 return goog.userAgent.WEBKIT ? 72 'color-stop(' + clr[0] + ', ' + clr[1].str + ')' : 73 clr[1].str + ' ' + clr[0] * 100 * this.rate + '%'; 74 }; 75 76 /** @inheritDoc */ 77 lime.fill.LinearGradient.prototype.setDOMStyle = function(domEl, shape) { 78 var grad, frame = shape.getFrame(), 79 width = frame.right - frame.left, 80 height = frame.bottom - frame.top; 81 82 if (!goog.userAgent.WEBKIT) { 83 84 //Endpoint calculation for non-webkit. 85 //If you are a math-wiz then optimize it 86 var x = (this.points_[2] - this.points_[0]) * width, 87 y = (this.points_[1] - this.points_[3]) * height, 88 x0 = frame.left + width * this.points_[0], 89 y0 = frame.top + height * this.points_[1], 90 angle = Math.atan2(y, x), tana = -y / x, p; 91 92 if (tana == Infinity) tana = Math.pow(10, 10); 93 94 if (angle > 0 && angle < Math.PI / 2) { 95 p = [frame.right, frame.top]; 96 } 97 else if (angle > 0) { 98 p = [frame.left, frame.top]; 99 } 100 else if (angle > -Math.PI / 2) { 101 p = [frame.right, frame.bottom]; 102 } 103 else { 104 p = [frame.left, frame.bottom]; 105 } 106 var xx = (p[1] + (1 / tana) * p[0] - y0 + tana * x0) / 107 (tana + 1 / tana), 108 yy = (tana * xx + y0 - x0 * tana); 109 xx -= x0; 110 yy -= y0; 111 this.rate = Math.sqrt((x * x + y * y) / (xx * xx + yy * yy)); 112 } 113 var colors = goog.array.map(this.colors_, this.formatColorStop_, this); 114 115 116 if (goog.userAgent.WEBKIT) { 117 grad = '-webkit-gradient(linear,' + this.points_[0] * 100 + '% ' + 118 this.points_[1] * 100 + '%,' + this.points_[2] * 100 + '% ' + 119 this.points_[3] * 100 + '%,' + colors.join(',') + ')'; 120 } 121 else { 122 123 grad = 'linear-gradient(' + this.points_[0] * 100 + '% ' + 124 this.points_[1] * 100 + '% ' + 125 Math.atan2((this.points_[1] - this.points_[3]) * height, 126 (this.points_[2] - this.points_[0]) * width) + 'rad,' + 127 colors.join(',') + ')'; 128 } 129 130 if (goog.userAgent.GECKO) grad = '-moz-' + grad; 131 132 domEl.style['background'] = grad; 133 }; 134 135 /** @inheritDoc */ 136 lime.fill.LinearGradient.prototype.setCanvasStyle = function(context, shape) { 137 var p = this.points_, 138 frame = shape.getFrame(), 139 width = frame.right - frame.left, 140 height = frame.bottom - frame.top; 141 142 var grad = context.createLinearGradient( 143 frame.left + width * p[0], 144 frame.top + height * p[1], 145 frame.left + width * p[2], 146 frame.top + height * p[3] 147 ); 148 149 for (var i = 0; i < this.colors_.length; i++) { 150 grad.addColorStop(this.colors_[i][0], this.colors_[i][1].str); 151 } 152 context.fillStyle = grad; 153 }; 154