I am new to grails. I am not able to render the JFree Chart BAr graph to my gsp. rather it is being rendered as individual image. I want bboth my gsp forms and chart to be rendered on the same gsp. Please help!!!!!!
def chart = ...
def buffer = chart.createBufferesImage( 700, 200 )
def bytes = EncoderUtil.encode( buffer, 'png' )
response.contentType = 'image/png'
response.contentLength = bytes.length
def out = response.outputStream
out.write( bytes )
out.flush()
out.close()
from Cartagena Colombia !!!
Related
I'm getting this error while I try to convert certain part of my page into a PDF (the page is like a group of charts and all of them are surrounded by a container called custom-view)
This is how my function looks like:
export function handleDownloadPdf() {
const element = document.getElementsByClassName("custom-view")[3];
html2canvas(element).then(canvas => {
const imgData = canvas.toDataURL("image/png");
const pdf = new jsPDF({
unit: "px",
format: [500, canvas.height],
});
pdf.addImage(imgData, "JPEG", 0, 0);
pdf.save("download.pdf");
});
}
I'm exporting this function from a component where all of my functions are to another component where the button to start the conversion exist. The reason why I put this: const element = document.getElementsByClassName("custom-view")[3]; as a index [3] is because I have other elements with custom-view class. The height of this custom-view container is dynamic, it gets changed based on the amount of charts there are in a custom view part.
The error I get is this one:
The browser I use is: Mozilla Firefox.
I am trying to generate a pdf from html divs with dynamic height and width. Below is the code.
let pages = this.rootDataContainer.nativeElement.getElementsByClassName('pdfpage');
for (let i = 0; i < pages.length; i++) {
this.pdfDoc.addHTML(pages[i], 0, 0, options, () => {
let pxHeight = pages[i].offsetHeight / scaleFactor;
this.pdfDoc.addPage(0, pxHeight);
this.counter = this.counter - 1;
});
}
There are couple of issues I am facing.
As addHTML is async, pages are added to pdf in random way.
height of the pdf page is either getting more or less height.
is there any way to set pdf size and sync the order of pages.
To sync I would use a recursive approach as in:
EDITED:
var pages = document.getElementsByClassName("pdfpage");
var pdfDoc = new jsPDF('p', 'pt', [0, 0]);
pdfDoc.deletePage(1);
pdfDoc.addPage(pages[0].clientWidth, pages[0].clientHeight);
var addDivToPdf = function(pageNr) {
pdfDoc.addHTML(pages[pageNr], 0, 0, {background:"#FFF"}, () => {
if (++pageNr < pages.length) {
//New added DIV dimensions here
pdfDoc.addPage(pages[pageNr].clientWidth, pages[pageNr].clientHeight);
addDivToPdf(pageNr);
} else {
pdfDoc.save("sample-file.pdf");
}
});
};
Notice I haven't use a for loop. This way the next page is added only when the previous is complete.
For the height, I'm not sure, scaleFactor must have the wrong units. It is not really clear if you want all pages to have the same size or you want different sizes to match the DIV height.
UPDATE: To control the widht and height according with the DIVs sizes, I have indicated 'pt' in the pdfDoc constructor:
var pdfDoc = new jsPDF('p', 'pt', [0, 0]);
However the first page appears to have always an standard size, so I have deleted it and added again with the desired size before adding the first DIV. The other pages can follow the normal flow:
pdfDoc.deletePage(1);
pdfDoc.addPage(pages[0].clientWidth, pages[0].clientHeight);
The CodePen is updated:
https://codepen.io/zameb/pen/BdbEVr
i am converting angular nvd3 chart to svg using html2canvas and canvg plugings but when i convert pie chart to png then i looks same as chart but when i convert line chart or area chart then its background goes to black and some circle drown on image.
My code is
var svgElements = $("#container").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', getStyle(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();
});
html2canvas($("#container"), {
onrendered: function (canvas) {
var a = document.createElement("a");
a.download = "Dashboard.png";
a.href = canvas.toDataURL("image/png");
a.click();
var imgData = canvas.toDataURL('image/png');
var doc = new jsPDF('p', 'mm','a4');
var width = doc.internal.pageSize.width;
var height = doc.internal.pageSize.height;
doc.addImage(imgData, 'PNG', 0, 0, width, height);
doc.save('Dashboard.pdf');
}
});
$("#container").find('.screenShotTempCanvas').remove();
$("#container").find('.tempHide').show().removeClass('tempHide');
Help me guys.
Thanks In Advance
Your svg elements are being styled by the external stylesheet nv.d3.min.css .
canvg seems unable to access external style sheets, so you need to append it directly in your svg node.
To do so, if your style sheet is hosted on the same domain as your scripts, you can do something like :
var sheets = document.styleSheets;
var styleStr = '';
Array.prototype.forEach.call(sheets, function(sheet){
try{ // we need a try-catch block for external stylesheets that could be there...
styleStr += Array.prototype.reduce.call(sheet.cssRules, function(a, b){
return a + b.cssText; // just concatenate all our cssRules' text
}, "");
}
catch(e){console.log(e);}
});
// create our svg nodes that will hold all these rules
var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
var style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
style.innerHTML = styleStr;
defs.appendChild(style);
// now append it in your svg node
thesvg[0].insertBefore(defs, thesvg[0].firstElementChild);
So now you can call the XMLSerializer, and canvg will be happy.
(note that this is not only a canvg limitation, the same applies for every way to draw an svg on a canvas).
Forked plunkr, where I copied the nv.d3.min.css's content to a same-origin style.css.
Very late to the conversation but I just wanted to add that the solution as described by Kaiido, put very simply, is to embed the styles into the SVG document directly.
In order to do this, you manipulate the DOM to make the SVG element look like this:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" version="1.1">
<defs>
<style>
.rectangleStyle{
width:200px;
height:100px;
stroke:black;
stroke-width: 6;
fill: green;
}
</style>
</defs>
<rect class="rectangleStyle"/>
</svg>
This is the code I'm using to create the Image that I'm inserting into a FlowDocument.
private static Image GetImage(string url)
{
if (url == null) throw new ArgumentNullException("url");
if (!(url.StartsWith("http://") || url.StartsWith("https://") || url.StartsWith("ftp://")))
return null;
var uri = new Uri(url, UriKind.Absolute);
var bmpImg = new BitmapImage(uri)
{
CacheOption = BitmapCacheOption.OnDemand,
};
if (bmpImg.CanFreeze) bmpImg.Freeze();
var img = new Image
{
Source = bmpImg,
Stretch = Stretch.Uniform,
Height = 120,
Width = 120,
};
return img;
}
When I create a document and insert an image from my server with
Designer.CaretPosition.Paragraph.Inlines.Add(image);
everything works fine - image displays as expected. Also, the main Google Logo image works fine, but the HackaDay Logo and others just display a blank image.
What could be the reason for this?
I think that some websites have hotlink protection. For example in my website I can link a photo in every page that it is in my domain and it works well, however if you try to link a photo in other domain, the photo doesn't load.
I am following the approach of
here. The problem is that all the pages are in first canvas. This is because I have only one canvas and I am not sure how I can generate more canvas one after other?
function handlePages(page)
{
var viewport = page.getViewport(canvas.width / page.getViewport(1.0).width);
var ctx = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({ canvasContext: ctx, viewport: viewport });
//Add it to the web page
div.appendChild( canvas);
//Move to next page
currPage++;
if ( $scope.pdfDoc !== null && currPage <= numPages )
{
$scope.pdfDoc.getPage( currPage ).then( handlePages );
}
}
you cut out part of the code from the linked answer that you took this from. notice the document.createElement( "canvas" ). That creates a new canvas for every page.