diff --git a/dist/all.js b/dist/all.js
index 4e8fee00..a8a090c9 100644
--- a/dist/all.js
+++ b/dist/all.js
@@ -2706,6 +2706,21 @@ fabric.util.animate = animate;
return oStyle;
};
+ function resolveGradients(instances) {
+ for (var i = instances.length; i--; ) {
+ var instanceFillValue = instances[i].get('fill');
+
+ if (/^url\(/.test(instanceFillValue)) {
+
+ var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1);
+
+ if (fabric.gradientDefs[gradientId]) {
+ instances[i].set('fill', fabric.gradientDefs[gradientId]);
+ }
+ }
+ }
+ }
+
/**
* Transforms an array of svg elements to corresponding fabric.* instances
* @static
@@ -2723,6 +2738,7 @@ fabric.util.animate = animate;
instances = instances.filter(function(el) {
return el != null;
});
+ resolveGradients(instances);
callback(instances);
}
}
@@ -2790,6 +2806,7 @@ fabric.util.animate = animate;
return function(doc, callback) {
if (!doc) return;
+
var descendants = fabric.util.toArray(doc.getElementsByTagName('*'));
var elements = descendants.filter(function(el) {
@@ -2822,6 +2839,8 @@ fabric.util.animate = animate;
height: height
};
+ fabric.gradientDefs = fabric.getGradientDefs(doc);
+
fabric.parseElements(elements, function(instances) {
if (callback) {
callback(instances, options);
@@ -2838,6 +2857,135 @@ fabric.util.animate = animate;
});
})(this);
+(function() {
+
+ /** @namespace */
+
+ fabric.Gradient = {
+
+ /**
+ * @method create
+ * @static
+ */
+ create: function(ctx, options) {
+ options || (options = { });
+
+ var x1 = options.x1 || 0,
+ y1 = options.y1 || 0,
+ x2 = options.x2 || ctx.canvas.width,
+ y2 = options.y2 || 0,
+ colorStops = options.colorStops;
+
+ var gradient = ctx.createLinearGradient(x1, y1, x2, y2);
+ for (var position in colorStops) {
+ var colorValue = colorStops[position];
+ gradient.addColorStop(position, colorValue);
+ }
+ return gradient;
+ },
+
+ /**
+ * @method fromElement
+ * @static
+ * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement
+ */
+ fromElement: function(el, ctx) {
+
+ /**
+ * @example:
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+ var colorStopEls = el.getElementsByTagName('stop'),
+ el,
+ offset,
+ colorStops = { };
+
+ for (var i = colorStopEls.length; i--; ) {
+ el = colorStopEls[i];
+ offset = parseInt(el.getAttribute('offset'), 10) / 100;
+ colorStops[offset] = el.getAttribute('stop-color');
+ }
+
+ return fabric.Gradient.create(ctx, {
+ x1: el.getAttribute('x1') || 0,
+ y1: el.getAttribute('y1') || 0,
+ x2: el.getAttribute('x2') || '100%',
+ y2: el.getAttribute('y2') || 0,
+ colorStops: colorStops
+ });
+ },
+
+ /**
+ * @method forObject
+ * @static
+ */
+ forObject: function(obj, ctx, options) {
+ options || (options = { });
+
+ _convertPercentUnitsToValues(obj, options);
+
+ var gradient = fabric.Gradient.create(ctx, {
+ x1: options.x1 - (obj.width / 2),
+ y1: options.y1 - (obj.height / 2),
+ x2: options.x2 - (obj.width / 2),
+ y2: options.y2 - (obj.height / 2),
+ colorStops: options.colorStops
+ });
+
+ return gradient;
+ }
+ };
+
+ function _convertPercentUnitsToValues(object, options) {
+ for (var prop in options) {
+ if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) {
+ var percents = parseFloat(options[prop], 10);
+ if (prop === 'x1' || prop === 'x2') {
+ options[prop] = object.width * percents / 100;
+ }
+ else if (prop === 'y1' || prop === 'y2') {
+ options[prop] = object.height * percents / 100;
+ }
+ }
+ }
+ }
+
+ /**
+ * Parses an SVG document, returning all of the gradient declarations found in it
+ * @static
+ * @function
+ * @memberOf fabric
+ * @method getGradientDefs
+ * @param {SVGDocument} doc SVG document to parse
+ * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition
+ */
+ function getGradientDefs(doc) {
+ var linearGradientEls = doc.getElementsByTagName('linearGradient'),
+ radialGradientEls = doc.getElementsByTagName('radialGradient'),
+ el,
+ gradientDefs = { };
+
+ for (var i = linearGradientEls.length; i--; ) {
+ el = linearGradientEls[i];
+ gradientDefs[el.id] = fabric.Gradient.fromElement(el);
+ }
+ for (var i = radialGradientEls.length; i--; ) {
+ el = radialGradientEls[i];
+ gradientDefs[el.id] = fabric.Gradient.fromElement(el);
+ }
+
+ return gradientDefs;
+ }
+
+ fabric.getGradientDefs = getGradientDefs;
+
+})();
(function(global) {
@@ -7024,6 +7172,10 @@ fabric.util.animate = animate;
*/
toJSON: function() {
return this.toObject();
+ },
+
+ setGradientFill: function(ctx, options) {
+ this.set('fill', fabric.Gradient.forObject(this, ctx, options));
}
});
diff --git a/fabric.js b/fabric.js
index aeca3c58..bd5b2a17 100644
--- a/fabric.js
+++ b/fabric.js
@@ -34,6 +34,7 @@ if (typeof console !== 'undefined') {
//= require "src/util"
//= require "src/parser"
+//= require "src/gradient"
//= require "src/point.class"
//= require "src/intersection.class"
diff --git a/src/gradient.js b/src/gradient.js
new file mode 100644
index 00000000..be829646
--- /dev/null
+++ b/src/gradient.js
@@ -0,0 +1,129 @@
+(function() {
+
+ /** @namespace */
+
+ fabric.Gradient = {
+
+ /**
+ * @method create
+ * @static
+ */
+ create: function(ctx, options) {
+ options || (options = { });
+
+ var x1 = options.x1 || 0,
+ y1 = options.y1 || 0,
+ x2 = options.x2 || ctx.canvas.width,
+ y2 = options.y2 || 0,
+ colorStops = options.colorStops;
+
+ var gradient = ctx.createLinearGradient(x1, y1, x2, y2);
+ for (var position in colorStops) {
+ var colorValue = colorStops[position];
+ gradient.addColorStop(position, colorValue);
+ }
+ return gradient;
+ },
+
+ /**
+ * @method fromElement
+ * @static
+ * @see http://www.w3.org/TR/SVG/pservers.html#LinearGradientElement
+ */
+ fromElement: function(el, ctx) {
+
+ /**
+ * @example:
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+ var colorStopEls = el.getElementsByTagName('stop'),
+ el,
+ offset,
+ colorStops = { };
+
+ for (var i = colorStopEls.length; i--; ) {
+ el = colorStopEls[i];
+ offset = parseInt(el.getAttribute('offset'), 10) / 100;
+ colorStops[offset] = el.getAttribute('stop-color');
+ }
+
+ return fabric.Gradient.create(ctx, {
+ x1: el.getAttribute('x1') || 0,
+ y1: el.getAttribute('y1') || 0,
+ x2: el.getAttribute('x2') || '100%',
+ y2: el.getAttribute('y2') || 0,
+ colorStops: colorStops
+ });
+ },
+
+ /**
+ * @method forObject
+ * @static
+ */
+ forObject: function(obj, ctx, options) {
+ options || (options = { });
+
+ _convertPercentUnitsToValues(obj, options);
+
+ var gradient = fabric.Gradient.create(ctx, {
+ x1: options.x1 - (obj.width / 2),
+ y1: options.y1 - (obj.height / 2),
+ x2: options.x2 - (obj.width / 2),
+ y2: options.y2 - (obj.height / 2),
+ colorStops: options.colorStops
+ });
+
+ return gradient;
+ }
+ };
+
+ function _convertPercentUnitsToValues(object, options) {
+ for (var prop in options) {
+ if (typeof options[prop] === 'string' && /^\d+%$/.test(options[prop])) {
+ var percents = parseFloat(options[prop], 10);
+ if (prop === 'x1' || prop === 'x2') {
+ options[prop] = object.width * percents / 100;
+ }
+ else if (prop === 'y1' || prop === 'y2') {
+ options[prop] = object.height * percents / 100;
+ }
+ }
+ }
+ }
+
+ /**
+ * Parses an SVG document, returning all of the gradient declarations found in it
+ * @static
+ * @function
+ * @memberOf fabric
+ * @method getGradientDefs
+ * @param {SVGDocument} doc SVG document to parse
+ * @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition
+ */
+ function getGradientDefs(doc) {
+ var linearGradientEls = doc.getElementsByTagName('linearGradient'),
+ radialGradientEls = doc.getElementsByTagName('radialGradient'),
+ el,
+ gradientDefs = { };
+
+ for (var i = linearGradientEls.length; i--; ) {
+ el = linearGradientEls[i];
+ gradientDefs[el.id] = fabric.Gradient.fromElement(el);
+ }
+ for (var i = radialGradientEls.length; i--; ) {
+ el = radialGradientEls[i];
+ gradientDefs[el.id] = fabric.Gradient.fromElement(el);
+ }
+
+ return gradientDefs;
+ }
+
+ fabric.getGradientDefs = getGradientDefs;
+
+})();
\ No newline at end of file
diff --git a/src/object.class.js b/src/object.class.js
index c8970d02..8aba1225 100644
--- a/src/object.class.js
+++ b/src/object.class.js
@@ -1270,6 +1270,10 @@
toJSON: function() {
// delegate, not alias
return this.toObject();
+ },
+
+ setGradientFill: function(ctx, options) {
+ this.set('fill', fabric.Gradient.forObject(this, ctx, options));
}
});
diff --git a/src/parser.js b/src/parser.js
index c83b1e8b..d0c2bda5 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -285,6 +285,22 @@
}
return oStyle;
};
+
+ function resolveGradients(instances) {
+ for (var i = instances.length; i--; ) {
+ var instanceFillValue = instances[i].get('fill');
+
+ if (/^url\(/.test(instanceFillValue)) {
+
+ // url(#grad1) --> grad1
+ var gradientId = instanceFillValue.slice(5, instanceFillValue.length - 1);
+
+ if (fabric.gradientDefs[gradientId]) {
+ instances[i].set('fill', fabric.gradientDefs[gradientId]);
+ }
+ }
+ }
+ }
/**
* Transforms an array of svg elements to corresponding fabric.* instances
@@ -303,6 +319,7 @@
instances = instances.filter(function(el) {
return el != null;
});
+ resolveGradients(instances);
callback(instances);
}
}
@@ -373,6 +390,7 @@
return function(doc, callback) {
if (!doc) return;
+
var descendants = fabric.util.toArray(doc.getElementsByTagName('*'));
var elements = descendants.filter(function(el) {
@@ -405,6 +423,8 @@
width: width,
height: height
};
+
+ fabric.gradientDefs = fabric.getGradientDefs(doc);
fabric.parseElements(elements, function(instances) {
if (callback) {
diff --git a/test/demo/demo.js b/test/demo/demo.js
index 3e8bbc00..38acacf0 100644
--- a/test/demo/demo.js
+++ b/test/demo/demo.js
@@ -355,4 +355,20 @@
initAligningGuidelines(canvas);
}
+ document.getElementById('gradientify').onclick = function() {
+ var obj = canvas.getActiveObject();
+ if (obj) {
+ obj.setGradientFill(canvas.getContext(), {
+ x2: (getRandomInt(0, 1) ? 0 : obj.width),
+ y2: (getRandomInt(0, 1) ? 0 : obj.height),
+ colorStops: {
+ 0: '#' + getRandomColor(),
+ 1: '#' + getRandomColor()
+ }
+ });
+ canvas.renderAll();
+ console.log(getRandomNum(0, 1));
+ }
+ };
+
})(this);
\ No newline at end of file
diff --git a/test/demo/index.html b/test/demo/index.html
index eae74457..2e3cc239 100644
--- a/test/demo/index.html
+++ b/test/demo/index.html
@@ -50,17 +50,25 @@
Add SVG shapes to canvas:
+
+
+
+
+
+
+
+
@@ -75,16 +83,19 @@
+
+
+
-
+
@@ -94,7 +105,9 @@
-
+
+
+
@@ -115,6 +128,10 @@
-
+
+ -
+
+
-