diff --git a/src/shapes/object.class.js b/src/shapes/object.class.js index 161e8ae2..8c9379bf 100644 --- a/src/shapes/object.class.js +++ b/src/shapes/object.class.js @@ -744,6 +744,16 @@ */ lockScalingFlip: false, + + /** + * When `true`, object is not exported in SVG or OBJECT/JSON + * since 1.6.3 + * @type Boolean + * @default + */ + + excludeFromExport: false, + /** * List of properties to consider when checking if state * of an object is changed (fabric.Object#hasStateChanged) diff --git a/src/static_canvas.class.js b/src/static_canvas.class.js index 4a23a2fb..9a60e1a6 100644 --- a/src/static_canvas.class.js +++ b/src/static_canvas.class.js @@ -1073,9 +1073,11 @@ * @private */ _toObjects: function(methodName, propertiesToInclude) { - return this.getObjects().map(function(instance) { - return this._toObject(instance, methodName, propertiesToInclude); - }, this); + return this.getObjects().filter(function(object) { + return !object.excludeFromExport; + }).map(function(instance) { + return this._toObject(instance, methodName, propertiesToInclude); + }, this); }, /** @@ -1296,11 +1298,15 @@ * @private */ _setSVGObjects: function(markup, reviver) { + var instance, originalProperties; for (var i = 0, objects = this.getObjects(), len = objects.length; i < len; i++) { - var instance = objects[i], - //If the object is in a selection group, simulate what would happen to that - //object when the group is deselected - originalProperties = this._realizeGroupTransformOnObject(instance); + instance = objects[i]; + if (instance.excludeFromExport) { + continue; + } + //If the object is in a selection group, simulate what would happen to that + //object when the group is deselected + originalProperties = this._realizeGroupTransformOnObject(instance); markup.push(instance.toSVG(reviver)); this._unwindGroupTransformOnObject(instance, originalProperties); } diff --git a/test/unit/canvas_static.js b/test/unit/canvas_static.js index 526c991f..a2caec79 100644 --- a/test/unit/canvas_static.js +++ b/test/unit/canvas_static.js @@ -586,6 +586,80 @@ canvas.renderOnAddRemove = true; }); + test('toSVG with reviver', function() { + ok(typeof canvas.toSVG == 'function'); + canvas.clear(); + + var circle = new fabric.Circle(), + rect = new fabric.Rect(), + path1 = new fabric.Path('M 100 100 L 300 100 L 200 300 z'), + tria = new fabric.Triangle(), + polygon = new fabric.Polygon([{x: 10, y: 12},{x: 20, y: 22}]), + polyline = new fabric.Polyline([{x: 10, y: 12},{x: 20, y: 22}]), + line = new fabric.Line(), + text = new fabric.Text('Text'), + group = new fabric.Group([text, line]), + ellipse = new fabric.Ellipse(), + image = new fabric.Image({width: 0, height: 0}), + imageBG = new fabric.Image({width: 0, height: 0}), + imageOL = new fabric.Image({width: 0, height: 0}), + path2 = new fabric.Path('M 0 0 L 200 100 L 200 300 z'), + path3 = new fabric.Path('M 50 50 L 100 300 L 400 400 z'), + pathGroup = new fabric.PathGroup([path2, path3]); + + canvas.renderOnAddRemove = false; + canvas.add(circle, rect, path1, tria, polygon, polyline, group, ellipse, image, pathGroup); + canvas.setBackgroundImage(imageBG); + canvas.setOverlayImage(imageOL); + var reviverCount = 0, + len = canvas.size() + group.size() + pathGroup.paths.length; + + function reviver(svg) { + reviverCount++; + return svg; + } + + canvas.toSVG(null, reviver); + equal(reviverCount, len + 2, 'reviver should include background and overlay image'); + canvas.setBackgroundImage(null); + canvas.setOverlayImage(null); + canvas.renderOnAddRemove = true; + }); + + test('toSVG with exclude from export', function() { + ok(typeof canvas.toSVG == 'function'); + canvas.clear(); + + var circle = new fabric.Circle({excludeFromExport: true}), + rect = new fabric.Rect({excludeFromExport: true}), + path1 = new fabric.Path('M 100 100 L 300 100 L 200 300 z'), + tria = new fabric.Triangle(), + polygon = new fabric.Polygon([{x: 10, y: 12},{x: 20, y: 22}]), + polyline = new fabric.Polyline([{x: 10, y: 12},{x: 20, y: 22}]), + line = new fabric.Line(), + text = new fabric.Text('Text'), + group = new fabric.Group([text, line]), + ellipse = new fabric.Ellipse(), + image = new fabric.Image({width: 0, height: 0}), + path2 = new fabric.Path('M 0 0 L 200 100 L 200 300 z'), + path3 = new fabric.Path('M 50 50 L 100 300 L 400 400 z'), + pathGroup = new fabric.PathGroup([path2, path3]); + + canvas.renderOnAddRemove = false; + canvas.add(circle, rect, path1, tria, polygon, polyline, group, ellipse, image, pathGroup); + var reviverCount = 0, + len = canvas.size() + group.size() + pathGroup.paths.length; + + function reviver(svg) { + reviverCount++; + return svg; + } + + canvas.toSVG(null, reviver); + equal(reviverCount, len - 2, 'reviver should not include objects with excludeFromExport'); + canvas.renderOnAddRemove = true; + }); + test('toJSON', function() { ok(typeof canvas.toJSON == 'function'); equal(JSON.stringify(canvas.toJSON()), '{"objects":[],"background":""}'); @@ -668,6 +742,17 @@ equal(canvas.toObject().objects[0].type, rect.type); }); + test('toObject excludeFromExport', function() { + var rect = makeRect(), rect2 = makeRect(), rect3 = makeRect(); + canvas.clear(); + canvas.add(rect, rect2, rect3); + equal(canvas.toObject().objects.length, 3, 'all objects get exported'); + rect.excludeFromExport = true; + rect2.excludeFromExport = true; + equal(canvas.toObject().objects.length, 1, 'only one object gets exported'); + }); + + test('toDatalessObject', function() { ok(typeof canvas.toDatalessObject == 'function'); var expectedObject = {