How to align text in center using jspdf - jspdf

How to align text center using jsPDF.
var doc = new jsPDF();
doc.text(40, 250, 'Hi How are you');

If you are using the latest version (1.1.135) the api has changed some for the text function. It now reads as:
API.text = function(text, x, y, flags, angle, align);
If you don't need to use the flags or angle though, you can simply use:
var doc = new jsPDF();
doc.text('Hi How are you', 40, 250, 'center');
Keep in mind that the center call uses the x parameter now as the center of the text string, and not the left most border as it does when rendering left aligned.
Link to source
Edit:
Alternately you can calculate the proper x offset to just use the text function normally like so:
var text = "Hi How are you",
xOffset = (doc.internal.pageSize.width / 2) - (doc.getStringUnitWidth(text) * doc.internal.getFontSize() / 2);
doc.text(text, xOffset, 250);

Angular 6.
Footer align to horizontally center
var doc = new jsPDF();
var pageHeight = doc.internal.pageSize.height || doc.internal.pageSize.getHeight();
var pageWidth = doc.internal.pageSize.width || doc.internal.pageSize.getWidth();
// FOOTER
let str = "Your footer text";
doc.setTextColor(100);
doc.setFontSize(10);
doc.text(str, pageWidth / 2, pageHeight - 10, {align: 'center'});
doc.save("example.pdf");

Above answers didn't work for me, I ended up doing the following to center the text
let textX = (doc.internal.pageSize.getWidth() - doc.getTextWidth(text))/2
doc.text(text, textX, textY);

this worked:
var xOffset = doc.internal.pageSize.width / 2
doc.text('hello world', xOffset, 8, {align: 'center'});

2022: this works assuming your page width is 210 (default A4).
doc.text("This is centred text.", 105, 80, null, null, "center");
Here's a link to their live demo per the README:
http://raw.githack.com/MrRio/jsPDF/master/index.html

2022: I'm finding that JSPDF is buggy. It took a while to figure out how to install the advertised 'runs in a browser' implementation for a PHP app instead of a JS front end framework. There's a line that's required window.jsPDF = window.jspdf.jsPDF; that isn't mentioned anywhere in the documentation, I had to go through a downloaded example piece by piece to find it. Now I'm finding that the center text function doesn't work. In 2 different local environments and a JSFiddle, on multiple browsers, it sends the text off the left side of the page when the align:center option is implemented. While the above solution works, it breaks down if text is longer than one line, which, incidentally, is another out of the box bug - the text runs out of the document instead of wrapping, and there is no wrap option. So, it seems after all these hours I'm out of luck and I'll have to go a different route. Plugin is not maintained and this should be noted in documentation. Recommend to not waste your time.

This works somewhat, but isn't precise, if you know please tell me why.
I calculate the width of my text in order to center it myself.
For this, I used the getTextDimensions() method on my jsPDF object
var pdf = new jsPDF({
orientation : 'p',
unit: 'px',
format: [500, 750],
putOnlyUsedFonts:true
});
var textDimensions = pdf.getTextDimensions('MyText');
You can now use textDimensions.w to get text-width and textDimensions.h for height
Then use this to center your text.
var textWidth = textDimensions.w;
pdf.text('MyText', (pdfWidth / 2) - (textWidth / 2), 100);
BUT: You need to know your PDF's width to do this.
I 'solved' this by defining height and width myself, but you can easily find height and width of common formats online.
Like A4: 210mm*297mm.
Just remember to set unit: 'mm' when creating your jsPDF.

var doc = new jsPDF();
// set midPage for variable use
var midPage = doc.internal.pageSize.getWidth()/2
// Default is 210 mm so default midway by value is 105
doc.setFontSize(40);
doc.text("Octonyan loves jsPDF", 105, 15, null, null, "center");
// Better to use a variable "midPage" (from above)
doc.setFontSize(30);
doc.text("Centered (USA), Centred (UK)", midPage , 30, null, null, "center");

Related

jsPDF - practical example for a fit-to-width shopping cart HTML page?

I'm trying to implement jsPDF pdf saving in a Vue app and I'm finding it overwhelming and nearly impossible to affect any visual change in the output.
The current results are: gigantic text and huge images.
Is there a way to get it to respect any of my CSS, #mediap print or otherwise, particularly for div borders?
The docs are very deep so I'd love an example of how to take a div-based table-like layout—e.g. a shopping cart—and fit it to width. I'd also love tips on avoid content bleeding across page breaks.
I've tried doc.setFont, doc.setFontSize and other methods and nothing changes the output.
this.doc.html(document.getElementById("pdfList"), {
callback: function (doc) {
doc.save("Cycad Inventory");
},
x: 40,
y: 40,
});
exportPDF = () => {
const unit = "pt";
const size = "A4"; // Use A1, A2, A3 or A4
const orientation = "portrait"; // portrait or landscape
const marginLeft = 30;
const doc = new jsPDF(orientation, unit, size);
doc.setFontSize(14);
const title = "Report";
const headers = [["Time", "Source", "Destination", "Protocol", "Length"]];
const data = this.state.ipData.map(elt => [elt.time, elt.source, elt.destination, elt.protocol, elt.length]);
let content = {
startY: 50,
head: headers,
body: data,
}
doc.text(title, marginLeft, 40);
doc.autoTable(content);
doc.save(this.state.ipData.fileName);
}
This is a code I used in reactJS. I hope this will help you to do changes to your code. Here I have declared the height, width, font sizes margins.

jsPDF- html() new function has no feature to set margin to pdf page

i am using jsPDF into vue cli application, but i am unable to find any solution to set the margins to the pdf page. all the text and images are getting overflowed on the pages.
i want to set all the four margins. the syntax to set margins given in the jsPDF documentation is also not working.
this is my function to generate and download pdf:
downloadpdf() {
var pdf = new jsPDF("p", "pt", "a4");
pdf.setFontSize("10");
pdf.setLineWidth("100");
pdf.setTextColor("darkblue");
// Printing text
var vuejsinformation = `JQuery is a lightweight, "write less, do more", JavaScript library.`;
pdf.text(vuejsinformation, 10, 10);
//pdf.save("Sample.pdf");
// Printing a complete div container who has class pdfrapper
pdf.html(window.jQuery(".pdfwrapper").get(0), {
callback: function (pdf) {
pdf.save("Sample.pdf");
},
x: 10,
y: 10,
});
},
how to set all the four margins ?
You can add an option var in the jspdf.html() method like this:
jspdf.html(src, {
margin: number,
html2canvas: {width: number, height: number, ...}
...
})
However there seems to be an issue where the margin is ignored when using this method see https://github.com/MrRio/jsPDF/issues/2924.
It will probably be fixed soon :).
Here's the documentation for the jspdf.html() method http://raw.githack.com/MrRio/jsPDF/master/docs/module-html.html
This example for jsPDF version 2.1.1 should give you an idea on how to setup the margins.
var pageWidth = 8.5,
lineHeight = 1.2,
margin = 0.5,
maxLineWidth = pageWidth - margin * 2,
fontSize = 24,
ptsPerInch = 72,
oneLineHeight = (fontSize * lineHeight) / ptsPerInch,
text =
"Two households, both alike in dignity,\n" +
"In fair Verona, where we lay our scene,\n" +
"From ancient grudge break to new mutiny,\n" +
"Where civil blood makes civil hands unclean.\n" +
"From forth the fatal loins of these two foes\n" +
"A pair of star-cross'd lovers take their life;\n" +
"Whole misadventured piteous overthrows\n" +
"Do with their death bury their parents' strife.\n" +
"The fearful passage of their death-mark'd love,\n" +
"And the continuance of their parents' rage,\n" +
// Notice that the following will be wrapped to two lines automatically!
"Which, but their children's end, nought could remove, Is now the two hours' traffic of our stage;\n" +
"The which if you with patient ears attend,\n" +
"What here shall miss, our toil shall strive to mend.",
doc = new jsPDF({
unit: "in",
lineHeight: lineHeight
}).setProperties({ title: "String Splitting" });
// splitTextToSize takes your string and turns it in to an array of strings,
// each of which can be displayed within the specified maxLineWidth.
var textLines = doc
.setFont("helvetica")
.setFontSize(fontSize)
.splitTextToSize(text, maxLineWidth);
// doc.text can now add those lines easily; otherwise, it would have run text off the screen!
doc.text(textLines, margin, margin + 2 * oneLineHeight);
// You can also calculate the height of the text very simply:
var textHeight = (textLines.length * fontSize * lineHeight) / ptsPerInch;
doc
.setFont("Helvetica", "bold")
.text(
"Text Height: " + textHeight + " inches",
margin,
margin + oneLineHeight
);

Bug in new highcharts renderer?

The following jsfiddle shows an example where I'm placing text on the chart, getting the width/height of that text, then using the width/height to work out where to place the same text again, but this time in the middle of the chart, and with a bounding box around it:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/3/
The above is using highcharts 4.0.4.
some code
Here is the exact same code, but using highcharts 4.1.1:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/4/
The bounding box has been placed around the first-placed text, despite using the x,y,width,height information from the second-placed text to create the bounding box.
Is this a bug in the new version?
Is there a better way to work out place text, with a bounding box, bang in the middle of a chart? Till now, I've been placing (invisible) dummy text, using width/height of that to work out where to place the real text, then adding the bounding box. Which is why I've run into this issue in the new version.
Well I'm still not sure why the example in the OP broke going from 4.0.4 to 4.1.1, but a partial answer to my question, which at least provides a solution that works even in 4.1.1, is given by the following jsfiddle:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/7/
text = chart.renderer.text("My Text").add();
textBBox = text.getBBox();
x = chart.plotLeft + (chart.plotWidth * 0.5) - (textBBox.width * 0.5);
y = chart.plotTop + (chart.plotHeight * 0.5) - (textBBox.height * 0.25);
text.attr({x: x, y: y, zIndex: 10});
rect = chart.renderer.rect(x, y, textBBox.width, textBBox.height, 2)
.attr({
fill: '#FFFFEF',
stroke: 'gray',
'stroke-width': 1,
zIndex: 9
})
.add();
rectBBox = rect.getBBox();
rect.attr({y: y - rectBBox.height*0.5 - textBBox.height*0.25});
A second mystery is why it's textBBox.height * 0.25 and not textBBox.height * 0.5...
EDIT... dang! The new solution breaks when I add a <br> to split the text across lines:
http://jsfiddle.net/drmrbrewer/mfr0rd4b/8/
Any idea how to fix that?

awesome wm taglist size

Can't find any manual about changing width of taglist element size.
Taglist element is wider than icons I had set. It looks really awful =(
Screenshot: http://s12.postimg.org/fkva7xywd/Screenshot_16_02_2014_16_04_07.png
Taglist element consist of icon, text and gap between them. This gap defined in awful.widget.common.list_update function in line
m = wibox.layout.margin(tb, 4, 4)
Despite you have no text, double gap is still here. To solve this problem you can copy list_update function to your rc file, fix it and send as fifth(!) argument in awful.widget.taglist.
just tell your imagebox not to be resizable, example:
wibox.widget.imagebox(beautiful.clock, false)
or you can even resize you wibox:
mywibox[s] = awful.wibox({ position = "top", screen = s, height = 32 })
you just need to modify height value
or another method using wibox.layout.constraint:
clock_icon = wibox.widget.imagebox(beautiful.clock, true)
local const = wibox.layout.constraint()
const:set_widget(clock_icon)
const:set_strategy("exact")
const:set_height(16)
then, instead of adding your icon to the layout, just add the constraint.

SVG 'getBBox' fails in a jQueryUI tab

I have a stand-alone SVG chart generator that works with all the major browsers. However, I've just added code to display the charts inside a jQuery UI tab, and the code has broken. Specifically, 'getBBox' now generally fails. It throws an exception in FF, works as expected in Opera, and gives the wrong answer in Chrome and Safari.
The difference between the old and new code is only, I think, in my understanding of what a 'document' is inside a tab. In the old stand-alone code, I could display a rectangle and get it's bbox as follows (in all browsers):
var svgDocument;
var svgNS = "http://www.w3.org/2000/svg";
...
if(window.svgDocument == null)
svgDocument = evt.target.ownerDocument;
...
var lbox = svgDocument.createElementNS(svgNS, "rect");
lbox.setAttributeNS(null, "x", 50);
lbox.setAttributeNS(null, "y", 50);
lbox.setAttributeNS(null, "width", 40);
lbox.setAttributeNS(null, "height", 40);
lbox.setAttributeNS(null, "stroke", "#E810D6");
lbox.setAttributeNS(null, "stroke-width", 2);
lbox.setAttributeNS(null, "fill-opacity", 1);
lbox.setAttributeNS(null, "stroke-opacity", 1);
lbox.setAttributeNS(null, "stroke-dasharray", 0);
svgDocument.documentElement.appendChild(lbox); // displays the box
var bbox = lbox.getBBox(); // gets the box bounds
The problem is that, when I try to display inside a tab, it's not obvious what svgDocument should be. This is my current code:
var svgDocument = document;
var svgNS = "http://www.w3.org/2000/svg";
var svgRoot;
...
// handle jQuery UI tabs as follows:
var top, svg, chart;
top = $(ui.panel).get(0);
svg = svgDocument.createElementNS(svgNS, "svg");
chart = "chart" + "-" + ui.panel.id;
svg.setAttributeNS(null, "id", chart);
top.appendChild(svg);
svgRoot = svgDocument.getElementById(chart);
...
// SVG draw is identical, except that svgDocument.documentElement is now svgRoot:
var lbox = svgDocument.createElementNS(svgNS, "rect");
lbox.setAttributeNS(null, "x", 50);
lbox.setAttributeNS(null, "y", 50);
lbox.setAttributeNS(null, "width", 40);
lbox.setAttributeNS(null, "height", 40);
lbox.setAttributeNS(null, "stroke", "#E810D6");
lbox.setAttributeNS(null, "stroke-width", 2);
lbox.setAttributeNS(null, "fill-opacity", 1);
lbox.setAttributeNS(null, "stroke-opacity", 1);
lbox.setAttributeNS(null, "stroke-dasharray", 0);
svgRoot.appendChild(lbox);
var bbox = lbox.getBBox();
The new code works "correctly" in Opera. FF, Chrome, and Safari display the rectangle correctly in the new tab, but get the bbox calculation wrong.
Any idea what I'm doing wrong here? Thanks.
[this is probably the same issue as Doing Ajax updates in SVG breaks getBBox, is there a workaround?, but there were no answers on that].
EDIT
I failed to mention that I'm rendering into a hidden tab, which is only displayed when the chart completes. Googling the FF exception code (in the comment below) indicates that there's some issue with getBBox when the element is not displayed. However, I don't understand this. I routinely use getBBox with visibility:hidden to size complex elements before displaying them, on all browsers (when I'm not using tabs). Besides, the rectangle in the example does actually render, as I can see it when the tab becomes visible, so shouldn't getBBox should also work?
Fixed - the answer is actually in the tabs documentation. Whoops.
From http://docs.jquery.com/UI/Tabs#...my_slider.2C_Google_Map.2C_sIFR_etc._not_work_when_placed_in_a_hidden_.28inactive.29_tab.3F
Any component that requires some dimensional computation for its initialization won't work in a hidden tab, because the tab panel itself is hidden via display: none so that any elements inside won't report their actual width and height (0 in most browsers).
There's an easy workaround. Use the off-left technique for hiding inactive tab panels. E.g. in your style sheet replace the rule for the class selector ".ui-tabs .ui-tabs-hide" with
.ui-tabs .ui-tabs-hide {
position: absolute;
left: -10000px;
}

Resources