I am having trouble in converting svg to PDF - svg

I am trying to convert SVG to PDF which is working fine but it is returning me a blank PDF. How can i achieve my SVG in pdf?
var doc = new jsPDF('p', 'pt', 'letter');
var test = $.get('/BarCodeSmallTag.svg', function (svgText) {
var svgAsText = new XMLSerializer().serializeToString(svgText.documentElement);
doc.addSVG(svgAsText, 20, 20, doc.internal.pageSize.width - 20 * 2)
// Save the PDF
doc.save('TestSVG.pdf');
});

Check here to do that using canvg https://stackoverflow.com/a/35788928/2090459
Basically you need get base64 image to add into PDF(jsPDF). If we have canvas we can convert to base64 string using .toDataURL().
Check the demo here http://jsfiddle.net/Purushoth/hvs91vpq/

Related

svg convert to canvas - can't generate multi pages pdf

I have 12 graphs and I want to generate pdf with 2 pages each page has 6 graphs.
However, when I convert svg to canvas, then the jspdf can only see part of both sub-dives.
$('#downloadx2').click(function() {
var svgElements = $("#body_id").find('svg');
//replace all svgs with a temp canvas
svgElements.each(function() {
var canvas, xml;
// canvg doesn't cope very well with em font sizes so find the calculated size in pixels and replace it in the element.
$.each($(this).find('[style*=em]'), function(index, el) {
$(this).css('font-size', getStylex(el, 'font-size'));
});
canvas = document.createElement("canvas");
canvas.className = "screenShotTempCanvas";
//convert SVG into a XML string
xml = (new XMLSerializer()).serializeToString(this);
// Removing the name space as IE throws an error
xml = xml.replace(/xmlns=\"http:\/\/www\.w3\.org\/2000\/svg\"/, '');
//draw the SVG onto a canvas
canvg(canvas, xml);
$(canvas).insertAfter(this);
//hide the SVG element
////this.className = "tempHide";
$(this).attr('class', 'tempHide');
$(this).hide();
});
var doc = new jsPDF("p", "mm");
var width = doc.internal.pageSize.width;
var height = doc.internal.pageSize.height;
html2canvas($("#div_pdf1"), {
onrendered: function(canvas) {
var imgData = canvas.toDataURL(
'image/png', 0.1);
doc.addImage(imgData, 'PNG', 5, 0, width, height/2,'','FAST');
doc.addPage();
}
});
html2canvas($("#div_pdf2"), {
onrendered: function(canvas2) {
var imgData2 = canvas2.toDataURL(
'image/png', 0.1);
doc.addImage(imgData2, 'PNG', 5, 0, width, height/2,'','FAST');
doc.save('.pdf');
}
});
});
<body id="body_id">
<div id="div_pdf1" >
<svg></svg>
<svg></svg>
<svg></svg>
</div>
<div id="div_pdf1" >
<svg></svg>
<svg></svg>
<svg></svg>
</div>
</body>
When I run this code, the generated pdf will view two pages with same canvas the first one (div_pdf1) div. So how to get both of them appearing in pdf as two pages.
You seem to be trying to run 2 parts in sequence but that's not how javascript works and actually runs your code.
No big deal, just a small misunderstanding between your mental model and the engine that executes the code.
A quick temporary debugging tool to see what's going on and verify that there is a discrepancy is to add console.log to key points and check the sequence of their printout once you run the code.
console.log('[1] just before: svgElements.each');
svgElements.each(function() {
console.log('[2] just after: svgElements.each');
And also around this part of the code:
console.log('[3] just before html2canvas-div_pdf1');
html2canvas($("#div_pdf1"), {
console.log('[4] just after html2canvas-div_pdf1');
Finally around this part of the code:
console.log('[5] just before html2canvas-div_pdf2');
html2canvas($("#div_pdf2"), {
console.log('[6] just after html2canvas-div_pdf2');
I suspect you'll see the code doesn't print the log lines in the order you think they will.
Next, you can try wrapping the 2 calls to html2canvas with one setTimeout function and force a delay in the execution of that code by an arbitrary amount of milliseconds.
Note that this is not the recommended final production quality solution but it will make the code output what you want.

fabricjs set boundingrect to the new object after cropping object using clipto method

I have clipped an image using clipto method of fabricjs and this works fine. But the problem is boudingrect is still to the actual image area. Is there any way to reset boundingrect same as new cropped image? I tried setCoords but this does not work.
FabricJS has two methods available to "crop" an object, the one you are using clipTo(), and a toDataURL() method. Using toDataURL() creates a new image with a reset boundingrect same as new cropped image.
fabric.Image.fromURL('data:image/;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACa0lEQVRYhbVXMW7bQBAcMgRTWCJdC+qFOLAaudFDnEKdYL1AfoCRB8gvkJJUAQw/RI3cSIBg13ZShzxWBEK6sEjf7e3dkYC8Fckhduf2doZHryzLEpY4e/mp3M+jEW7TB/bdq+457rMnpGVeP9v3p7b08K0oE7NoiHk0Yotfxxdt07UnsEy3Gomq+F32qKy+SQRtCVTtn0VDAEBS5nXx7//WbdPpBOQ9/3YywDwaYRYNsUy3dfHksMquHwLF27uieF+53JFFssFK7Gps3Zsg9j+bCcjFb07H+PrnFwD3ik14NYQyCWsH5OKe5wHQ206Lu/BqODkSGgFanBbp+iG71y7cpBDvy/MPxQeozmUdL9Nt3WIuOFyeKc4ntA5UbaRmIw8htyIXXg3mffakPNd8gNM5Tb4SOyySTWPc5hNaB+hA0eRyEQCIvdCKy8W52fDn0Qj7/lRZsazzxOJsosideOyF9XUVV91z7PtT3JyOEbiczaRjqhYT7vKRAGivY1rchdvy1zPQVMeiyFmfcOGm/MoQJmVeezsXsRcCPrTkTXEuf02Afs8/ygdo/kAG77JHiCLXzIjTuVzEhdvyByadfrQPVPmDldhpEpJ94OV/piWvQhS59Uwlihz9T533dw9xmz6oWyAHZXxsH6Dd0ghw7TqmDyzFzv41NHn2sXyAhkf/CxbJxvo9Nw2dCafnicvOwH4mpBKSk9t8oqmPXHYGynP2TNhGx01wk5SNBGQSLh27Tsm24iyBdW+i3I///rb6BPdfIOt83ZsobY8O5wMjAXlAuHB1hK7Wla/1rxlX3KZzV7QmYPIJ2z7b4hVhK2M6UYICmwAAAABJRU5ErkJggg==', function(origImage) {
var origBoundingRect = origImage.getBoundingRect();
fabric.Image.fromURL(origImage.toDataURL({
width: origImage.width - 5,
height: origImage.height - 5
}), function(newImage) {
var newBoundingRect = newImage.getBoundingRect();
console.log('origBoundingRect:\r\n' + JSON.stringify(origBoundingRect) + '\r\n\r\n' + 'newBoundingRect:\r\n' + JSON.stringify(newBoundingRect));
});
});
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.7/fabric.min.js"></script>
If you run the code snip-it above it logs to the console a before and after shot of the boundingrect.
Hope this helps, matey. Let me know if you have any further questions.

Render Svg to Pdf using jspdf

I am having trouble in rendering svg element to pdf using jspdf . Iam using plugin https://github.com/CBiX/svgToPdf.js/ to do this.
Below is my code
// I recommend to keep the svg visible as a preview
var tmp = document.getElementById("chartContainer");
var svgDoc = tmp.getElementsByTagName("svg")[0];
var pdf = new jsPDF('p', 'pt', 'a4');
svgElementToPdf(svgDoc, pdf, {
scale: 72 / 96, // this is the ratio of px to pt units
removeInvalid: false // this removes elements that could not be translated to pdf from the source svg
});
pdf.output('datauri'); // use output() to get the jsPDF buffer
It is generarting blank pdf. Please help
You can do that using canvg.
Step1: Get "SVG" markup code from DOM
var svg = document.getElementById('svg-container').innerHTML;
if (svg)
svg = svg.replace(/\r?\n|\r/g, '').trim();
Step 2:
Use canvg to create canvas from svg.
var canvas = document.createElement('canvas');
canvg(canvas, svg);
Step 3:
Create image from canvas using .toDataURL()
var imgData = canvas.toDataURL('image/png');
// Generate PDF
var doc = new jsPDF('p', 'pt', 'a4');
doc.addImage(imgData, 'PNG', 40, 40, 75, 75);
doc.save('test.pdf');
Check the demo here http://jsfiddle.net/Purushoth/hvs91vpq/193/
Canvg Repo: https://github.com/gabelerner/canvg
I've tried both svg2pdf.js and addSvgAsImage using canvg internally.
Both didn't work well for me, the resulting images in the pdf where either incorrectly positioned or displayed.
I've ended up doing the following which works very well:
convert the SVG to PNG without any libraries, see my answer to "Convert SVG to image (JPEG, PNG, etc.) in the browser".
just add the result to the pdf using the normal addImage method
I think the current jspdf version (2.3.1) has an addSvgAsImage method, but it takes the svg as a string. I guess you could use an ajax call to retrieve the SVG content, but I just have the SVG in my code and pass it in that way.

How do I fill/stroke an SVG file on my website?

I Googled this issue for about 30 minutes and was surprised nobody has asked so maybe it's not possible.
I'm using this line to embed the SVG file that I made in AI (note that when I saved the SVG, I had no fill OR stroke on the paths):
<object type="image/svg+xml" data="example.svg" height=600px width=600px>Your browser does not support SVG</object>
This obviously comes up with no image because the SVG file has no fill or stroke.
I tried adding in
...fill=yellow>
or
...style="fill:yellow;">
but I'm not having any luck. Thanks!
Have a nice trick: Embed it as <img> and use javascript to convert it into inline <svg> with this code (that came from SO I think). Now you can manipulate this SVG object
CODE::
/*
* Replace all SVG images with inline SVG
*/
jQuery('img.svg').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if(typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
});
});
Are you trying to add the fill or style on the object element? If so, that's not going to work. Those properties are not supported on the object element. You're going to have to add it into the SVG in the SVG file.

yui How to make in tag image does not necessarily will been to specify its size?

Good day.
I use script Imagecropper
Script:
<img src="http://test.com/img/1362244329.jpg" id="yui_img" height="768" width="1024">
<script>
(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event;
var crop = new YAHOO.widget.ImageCropper('yui_img');
})();
</script>
result:
But if i do not specify the image size, then i get next(see image):
<img src="http://test.com/img/1362244329.jpg" id="yui_img">
result:
And if i specify the wrong picture size, the window will increase the portion of the image:
<img src="http://test.com/img/1362244329.jpg" id="yui_img" height="333" width="500">
result:
How to make in tag image does not necessarily will been to specify its size?
First of all I'd like to point you to YUI 3 since YUI 2 is no longer supported. You shouldn't write new code using YUI 2. There's an ImageCropper component I wrote for YUI 3 that works just like the YUI 2 version in the YUI Gallery: http://yuilibrary.com/gallery/show/imagecropper. Since it copies what the YUI 2 ImageCropper did, it shares these issues with the older version.
What to do when the size of the image isn't specified
The reason why you're getting a small ImageCropper is that you're creating the widget before the image has been fetched and so the browser doesn't know its size yet. What you can do is wait for the image's onload event. You can listen to that event and create the ImageCropper after it fires:
(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event;
var yui_img = Dom.get('yui_img');
Event.addListener(yui_img, 'load', function () {
var crop = new YAHOO.widget.ImageCropper(yui_img);
});
})();
Why the ImageCropper doesn't work with images with the wrong size
Neither the YUI 2 ImageCropper nor my YUI 3 version work with images when they don't have the right size. The reason is that both use the background: url() CSS style for showing the image inside the crop area (the non-darkened part of the widget). CSS backgrounds don't let you use a resized/zoomed image.
I plan on using another strategy at some point for the YUI 3 version that will fix the issue. However, you need to keep in mind that the ImageCropper component is designed so that you send the crop coordinates to the server for it to actually crop the image. That means that if you have the wrong size set to the image, the coordinates that the image cropper returns with its getCropCoords method wouldn't be the coordinates that match with the full sized image. Instead you'd also have to send the server the size of the image you've been using and do extra math to crop the image correctly.
In conclusion, you shouldn't use the image with the wrong size. You can fix the size of the image in two ways:
Use the HTML5 naturalWidth and naturalHeight attributes of the image. Those return the real size of the image even if it's resized. Unfortunately these attributes are not yet supported by all browsers.
Create a new image with JS, set it the same src as the image you're using, listen to its load event and get that image's size.
Something like this:
(function () {
var Dom = YAHOO.util.Dom;
var yui_img = Dom.get('yui_img'),
new_img = new Image();
new_img.onload = function () {
yui_img.width = new_img.width;
yui_img.height = new_img.height;
// create the ImageCropper
};
new_img.src = yui_img.src;
}());
A YUI3 version
You can easily do all this with YUI3:
YUI().use('gallery-imagecropper', function (Y) {
var img = Y.one('#yui_img');
img.on('load', function () {
var cropper = new Y.ImageCroper({
srcNode: img,
width: img.get('width'),
height: img.get('height')
});
cropper.render();
});
});
Typo in code. Should be
var cropper = new Y.ImageCropper({
You missed a letter "p".

Resources