Export as image
Would it be possible to export the result as PNG image like the svg export ?
+1
:+1:
Saving as PNG is a little tricky. As the SVG is generated client side, the browser has to save the SVG as a PNG. A year ago when I last tried, I had mixed success getting this to work. I will revisit.
simplest way to get a PNG, is to port SVG to canvas, and then from canvas element get data image, and assign that to either img or a
i found an issue with this approach, and that is probably you had a mixed success, raphael.js doesn't produce valid SVG at times, if xlink namespaces are used, and in this case xlink:href is used quite a lot when relationships/signals are created.
hopefully next version of raphael will resolve that, there is a pull request to fix this particular issue.
question is weather js-sequence-diagram wants to pull as part of the project all of the dependencies that are used to create PNG (similar how raphael.js and others are pulled), or do we just want to address this as part of the documentation?
example uses canvg.js and patched version of raphael.js
below example can be previewed with all of the proper dependencies here on jsfiddle
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js"></script>
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/StackBlur.js"></script>
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/canvg.js"></script>
<script src="jquery.min.js"></script>
<script src="lodash.min.js"></script>
<script src="raphael-min.js"></script>
<script src="../build/sequence-diagram-min.js"></script>
</head>
<body>
<table border="1">
<thead>
<th>SVG</th>
<th>PNG</th>
<th>Anchor</th>
</thead>
<tbody>
<tr>
<td><div id="svgWrapper"></div></td>
<td><img id="myPNG"></img></td>
<td><a id="uriToPNG"></a></td>
</tr>
</tbody>
</table>
<script>
$(document).ready(function() {
// set svgWrapper content to blank
$("#svgWrapper").html('');
var diagram = Diagram.parse(
"Title: Sample Diagram\nA->B: message"
);
// draw SVG inside element with id of svgWrapper
diagram.drawSVG('svgWrapper', {
theme : 'hand'
});
// select container that is wraping SVG
var container = $('#svgWrapper');
// tring selected SVG
var content = container.html().trim();
// create canvas element
var canvas = document.createElement("canvas");
// transform and add SVG content to canvas
canvg(canvas, content);
// get data for image in the canvas
var theImage = canvas.toDataURL('image/png');
// add to anchor a href of produced data
$('#uriToPNG').attr({
'href' : theImage,
'download' : "image.png",
}).text("click here to download (chrome,firefox, opera)");
// add PNG to img element
$('#myPNG').attr('src', theImage);
});
</script>
</body>
</html>
There is an even simpler approach:
- Extract the SVG source code from the
<svg>element.svg.outerHTMLworks (at least in Chrome). - Load the source code (as a data URI) into an
<image>element.
At this stage you can already right-click and select "Save image" in Chrome. - Load the image data using
canvas2dContext.drawImage(img, 0, 0)into a canvas. - Save the canvas data as a PNG using
canvas.toDataURL("image/png").
jsFiddle demo: http://jsfiddle.net/0ktjqm9t/3/ (directly visiting http://jsfiddle.net/0ktjqm9t/3/show will show the data URI in the address bar in Chrome)
Caveats:
- Doesn't work in IE (tested with v11) due to some syntax errors. They probably come from the SVG document. Chrome is (apparently) less restrictive.
- There was once a bug in Webkit which disallowed canvas export after importing a data URI, see StackOverflow: "Accessing the SVG data through JavaScript"
- The image is cropped in the above demo. I don't know why.
- (At least) Chrome needs the following attribute on the root
<svg>element:
<svg xmlns="http://www.w3.org/2000/svg" ...>
<!-- Supplying some more attributes I found on MDN seems reasonable to me -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ...>
that example producing a broken image for me actually in safari.
@winfinit It definitely needs investigating. What is the browser compatibility like in your solution? I can't find information on that topic on canvg's Google Code website.
@ComFreek it looks like opera, safari (ios+osx), chrome are working, so browsers that support SVG. i just ran provided jsfiddle through browserstack, and it seems that everything rendered as expected.
That sounds nice!
Unfortunately - as I just tried - it doesn't work in IE 11 on Win 8.1:
File: show
HTML1503: Unexpected start tag.
File: show, Line: 93, Column: 9
HTML1512: Unmatched end tag.
File: show, Line: 100, Column: 33
SCRIPT5022: SyntaxError
File: canvg.js, Line: 145, Column: 5
The line from canvg.js:
else if (window.DOMParser)
{
var parser = new DOMParser();
return parser.parseFromString(xml, 'text/xml');
}
It seems that the SVG is ill-formed.
Ping! Has anyone reconsidered this?
I'm using this as an image src (new XMLSerializer).serializeToString(svg)
Works everywhere except ios safari. The functions returns wrong results.
Actually what I found is bugging:
<svg xmlns="http://www.w3.org/2000/svg" class="sequence simple" width="990.539px" height="401.203px" y="0" systemLanguage="" externalResourcesRequired="false" requiredFeatures="" transform="" preserveAspectRatio="xMidYMid meet" requiredExtensions="" viewBox="0 0 0 0" x="0">
It works if its:
<svg xmlns="http://www.w3.org/2000/svg" class="sequence simple" width="990.539px" height="401.203px">
The solution I found to display the generated SVG responsively via a element cross device.
After the svg is rendered I call:
// diagramDom is the element holding the svg
var svg = diagramDom.getElementsByTagName('svg')[0];
var img = document.createElement("IMG");
img.src = "";
setImageToSVG(img, svg);
diagramDom.appendChild(img);
function setImageToSVG(img, svg) {
//function to clean svg so it also works on iOs Safari
svg.removeAttribute("x");
svg.removeAttribute("y");
svg.removeAttribute("systemLanguage");
svg.removeAttribute("externalResourcesRequired");
svg.removeAttribute("requiredFeatures");
svg.removeAttribute("transform");
svg.removeAttribute("preserveAspectRatio");
svg.removeAttribute("requiredExtensions");
svg.removeAttribute("viewBox");
var xml = (new XMLSerializer).serializeToString(svg);
let string = `data:image/svg+xml;charset=utf-8,${xml}`;
img.src = string;
}