diff --git a/examples/SVG Export/Gradients.html b/examples/SVG Export/Gradients.html
new file mode 100644
index 00000000..0ac4b391
--- /dev/null
+++ b/examples/SVG Export/Gradients.html
@@ -0,0 +1,23 @@
+
+
+
+
+ Gradients
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/color/Gradient.js b/src/color/Gradient.js
index f6e6eb62..6c9b5117 100644
--- a/src/color/Gradient.js
+++ b/src/color/Gradient.js
@@ -25,6 +25,8 @@ var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
* @param {String} [type='linear'] 'linear' or 'radial'
*/
initialize: function(stops, type) {
+ // Define this Gradient's unique id.
+ this._id = ++Base._uid;
this.setStops(stops || ['white', 'black']);
this.type = type || 'linear';
},
diff --git a/src/svg/SvgExport.js b/src/svg/SvgExport.js
index 1119245f..52909e49 100644
--- a/src/svg/SvgExport.js
+++ b/src/svg/SvgExport.js
@@ -374,19 +374,56 @@ new function() {
return createElement('use', attrs);
}
- function exportColor(color) {
- /*
- var gradientSvg = getDefinition(symbol)
-
-
-
-
-
- */
- if (color.gradient) {
- return null;
+ function exportGradient(color) {
+ // NOTE: As long as the fillTransform attribute is not implemented,
+ // we need to create a separate gradient object for each gradient,
+ // even when they share the same gradient defintion.
+ // http://www.svgopen.org/2011/papers/20-Separating_gradients_from_geometry/
+ // TODO: Implement gradient mergin in SvgImport
+ var gradient = color.gradient,
+ gradientNode = getDefinition(color);
+ if (!gradientNode) {
+ var origin = color._origin,
+ destination = color._destination,
+ highlight = color._hilite,
+ attrs;
+ if (gradient.type == 'radial') {
+ attrs = {
+ cx: origin.x,
+ cy: origin.y,
+ r: origin.getDistance(destination)
+ };
+ if (highlight) {
+ attrs.fx = highlight.x;
+ attrs.fy = highlight.y;
+ }
+ } else {
+ attrs = {
+ x1: origin.x,
+ y1: origin.y,
+ x2: destination.x,
+ y2: destination.y
+ };
+ }
+ attrs.gradientUnits = 'userSpaceOnUse';
+ gradientNode = createElement(gradient.type + 'Gradient', attrs);
+ var stops = gradient._stops;
+ for (var i = 0, l = stops.length; i < l; i++) {
+ var stop = stops[i],
+ color = stop._color,
+ attrs = {
+ offset: stop._rampPoint,
+ 'stop-color': color.toCss(true)
+ };
+ // See applyStyle for an explanation of why there are separated
+ // opacity / color attributes.
+ if (color.getAlpha() < 1)
+ attrs['stop-opacity'] = color._alpha;
+ gradientNode.appendChild(createElement('stop', attrs));
+ }
+ setDefinition(gradient, gradientNode, 'gradient');
}
- return color.toCss(true); // false for noAlpha, see above
+ return 'url(#' + gradientNode.id + ')';
}
var exporters = {
@@ -417,11 +454,13 @@ new function() {
// separate the alpha value of colors with alpha into the
// separate fill- / stroke-opacity attribute:
if (entry.type === 'color' && value != null && value.getAlpha() < 1)
- attrs[entry.attribute + '-opacity'] = value.getAlpha();
+ attrs[entry.attribute + '-opacity'] = value._alpha;
attrs[entry.attribute] = value == null
? 'none'
: entry.type === 'color'
- ? exportColor(value)
+ ? value.gradient
+ ? exportGradient(value)
+ : value.toCss(true) // false for noAlpha, see above
: entry.type === 'array'
? value.join(',')
: entry.type === 'number'