how to export SVG graph to pdf - javascript

I am using a API which render the line graph in SVG but I am not able to export it into PDF like other graph which render in HTML5 canvas
$(function() {
// let's loop to build tooltips and x labels.
var thelabels = new Array(30);
for (var i = 0; i < 30; i++) {
thelabels[i] = (i % 6 === 0) ? (i + 1) + " september" : "";
}
// build the chart using the "google analytics" template.
$("#chart").chart({
template: "raphael_analytics",
labels: thelabels,
values: values()
});
// start a loop that sets new data in the chart every 5 seconds.
});
Code is available in jsfiddle
while searching I got a link where I can export SVG graph to PDF but the demo what they provided it is not working and they used Perl script to export.
I wanted to export from client/browser to canvas image data
Edited
I have seen one more library in github it allows you to download SVG to PDF from client side. But in the library they have used a object called "RGBColor(fillColor)" this throw an error like RGBColor is not defined so is there any library I need to include..???

I had to convert graphs and pie charts to pdf and wound up using this third party package. It converts HTML to PDF. Just render graph and then pass the URL to the converter. It worked great. Its called HiQPDf

Perhaps you can
print your webpage to PDF.
convert it using any script like svgToPdf.js.
To print as PDF, define a stylesheet for printing
#media print {
body * { visibility: hidden; }
#chart * { visibility: visible; }
#chart { position: absolute; top: 10px; left: 10px; }
}
and call print using javascript
var chart = document.getElementById('chart').innerHTML,
body = document.body.innerHTML;
document.body.innerHTML = chart;
window.print();
document.body.innerHTML = body;

This is not local but works fine. Using http://www.cloudformatter.com/css2pdf to render your chart. I added their javascript and a button to download the PDF.
http://jsfiddle.net/JehdF/1237/
<button onclick="return xepOnline.Formatter.Format('chart',{pageWidth:'11in', pageHeight:'8.5in',render:'download'});">Get PDF</button>
<div id="chart" style="width: 100%; height: 600px"></div>
Use instructions are here: http://www.cloudformatter.com/CSS2Pdf.APIDoc.Usage
Result:

Related

How to save current page as PDF using frontend JavaScript? [duplicate]

I have the following html code:
<!DOCTYPE html>
<html>
<body>
<p>don't print this to pdf</p>
<div id="pdf">
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
All I want to do is to print to pdf whatever is found in the div with an id of "pdf". This must be done using JavaScript. The "pdf" document should then be automatically downloaded with a filename of "foobar.pdf"
I've been using jspdf to do this, but the only function it has is "text" which accepts only string values. I want to submit HTML to jspdf, not text.
jsPDF is able to use plugins. In order to enable it to print HTML, you have to include certain plugins and therefore have to do the following:
Go to https://github.com/MrRio/jsPDF and download the latest Version.
Include the following Scripts in your project:
jspdf.js
jspdf.plugin.from_html.js
jspdf.plugin.split_text_to_size.js
jspdf.plugin.standard_fonts_metrics.js
If you want to ignore certain elements, you have to mark them with an ID, which you can then ignore in a special element handler of jsPDF. Therefore your HTML should look like this:
<!DOCTYPE html>
<html>
<body>
<p id="ignorePDF">don't print this to pdf</p>
<div>
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
Then you use the following JavaScript code to open the created PDF in a PopUp:
var doc = new jsPDF();
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 180,'elementHandlers': elementHandler
});
doc.output("dataurlnewwindow");
For me this created a nice and tidy PDF that only included the line 'print this to pdf'.
Please note that the special element handlers only deal with IDs in the current version, which is also stated in a GitHub Issue. It states:
Because the matching is done against every element in the node tree, my desire was to make it as fast as possible. In that case, it meant "Only element IDs are matched" The element IDs are still done in jQuery style "#id", but it does not mean that all jQuery selectors are supported.
Therefore replacing '#ignorePDF' with class selectors like '.ignorePDF' did not work for me. Instead you will have to add the same handler for each and every element, which you want to ignore like:
var elementHandler = {
'#ignoreElement': function (element, renderer) {
return true;
},
'#anotherIdToBeIgnored': function (element, renderer) {
return true;
}
};
From the examples it is also stated that it is possible to select tags like 'a' or 'li'. That might be a little bit to unrestrictive for the most usecases though:
We support special element handlers. Register them with jQuery-style
ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
There is no support for any other type of selectors (class, of
compound) at this time.
One very important thing to add is that you lose all your style information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3 etc., which was enough for my purposes. Additionally it will only print text within text nodes, which means that it will not print the values of textareas and the like. Example:
<body>
<ul>
<!-- This is printed as the element contains a textnode -->
<li>Print me!</li>
</ul>
<div>
<!-- This is not printed because jsPDF doesn't deal with the value attribute -->
<input type="textarea" value="Please print me, too!">
</div>
</body>
This is the simple solution. This works for me. You can use the javascript print concept and simple save this as pdf.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$("#btnPrint").live("click", function () {
var divContents = $("#dvContainer").html();
var printWindow = window.open('', '', 'height=400,width=800');
printWindow.document.write('<html><head><title>DIV Contents</title>');
printWindow.document.write('</head><body >');
printWindow.document.write(divContents);
printWindow.document.write('</body></html>');
printWindow.document.close();
printWindow.print();
});
</script>
</head>
<body>
<form id="form1">
<div id="dvContainer">
This content needs to be printed.
</div>
<input type="button" value="Print Div Contents" id="btnPrint" />
</form>
</body>
</html>
No depenencies, pure JS
To add CSS or images - do not use relative URLs, use full URLs http://...domain.../path.css or so. It creates separate HTML document and it has no context of main thing.
you can also embed images as base64
This served me for years now:
export default function printDiv({divId, title}) {
let mywindow = window.open('', 'PRINT', 'height=650,width=900,top=100,left=150');
mywindow.document.write(`<html><head><title>${title}</title>`);
mywindow.document.write('</head><body >');
mywindow.document.write(document.getElementById(divId).innerHTML);
mywindow.document.write('</body></html>');
mywindow.document.close(); // necessary for IE >= 10
mywindow.focus(); // necessary for IE >= 10*/
mywindow.print();
mywindow.close();
return true;
}
Of course this will open print dialog and user will have to know she/he can select print to pdf option, to get pdf. There may be printer pre-selected and if user confirms may get this document actually printed. To avoid such situation and to provide PDF without any extras, you need to make PDF file. Probably on the server side. You could have tiny html page with invoice only and convert it to PDF file with headless chrome. It's super easy with puppeteer. No need to install/config chrome, just install npm package puppeteer (managed by chrome team) and run it. Keep in mind this will actually launch real chrome just w/o GUI, so you need to have some RAM & CPU for this. Most servers will be fine with low enough traffic. Here is code sample but this must run on the BACKEND. Nodejs. Also it's slow call, it's resources intensive call. You should run it NOT on api call but e.g. after invoice was created - create pdf for it and store, if pdf was not generated yet, just show message to try again in couple minutes.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://your-domain.com/path-to-invoice', {
waitUntil: 'networkidle2',
});
await page.pdf({ path: 'invoice-file-path.pdf', format: 'a4' });
await browser.close();
})();
Learn more here: https://pptr.dev/
if you need to downloadable pdf of a specific page just add button like this
<h4 onclick="window.print();"> Print </h4>
use window.print() to print your all page not just a div
You can use autoPrint() and set output to 'dataurlnewwindow' like this:
function printPDF() {
var printDoc = new jsPDF();
printDoc.fromHTML($('#pdf').get(0), 10, 10, {'width': 180});
printDoc.autoPrint();
printDoc.output("dataurlnewwindow"); // this opens a new popup, after this the PDF opens the print window view but there are browser inconsistencies with how this is handled
}
As mentioned, you should use jsPDF and html2canvas. I've also found a function inside issues of jsPDF which splits automatically your pdf into multiple pages (sources)
function makePDF() {
var quotes = document.getElementById('container-fluid');
html2canvas(quotes, {
onrendered: function(canvas) {
//! MAKE YOUR PDF
var pdf = new jsPDF('p', 'pt', 'letter');
for (var i = 0; i <= quotes.clientHeight/980; i++) {
//! This is all just html2canvas stuff
var srcImg = canvas;
var sX = 0;
var sY = 980*i; // start 980 pixels down for every new page
var sWidth = 900;
var sHeight = 980;
var dX = 0;
var dY = 0;
var dWidth = 900;
var dHeight = 980;
window.onePageCanvas = document.createElement("canvas");
onePageCanvas.setAttribute('width', 900);
onePageCanvas.setAttribute('height', 980);
var ctx = onePageCanvas.getContext('2d');
// details on this usage of this function:
// https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);
// document.body.appendChild(canvas);
var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);
var width = onePageCanvas.width;
var height = onePageCanvas.clientHeight;
//! If we're on anything other than the first page,
// add another page
if (i > 0) {
pdf.addPage(612, 791); //8.5" x 11" in pts (in*72)
}
//! now we declare that we're working on that page
pdf.setPage(i+1);
//! now we add content to that page!
pdf.addImage(canvasDataURL, 'PNG', 20, 40, (width*.62), (height*.62));
}
//! after the for loop is finished running, we save the pdf.
pdf.save('test.pdf');
}
});
}
i use jspdf and html2canvas for css rendering and i export content of specific div as this is my code
$(document).ready(function () {
let btn=$('#c-oreder-preview');
btn.text('download');
btn.on('click',()=> {
$('#c-invoice').modal('show');
setTimeout(function () {
html2canvas(document.querySelector("#c-print")).then(canvas => {
//$("#previewBeforeDownload").html(canvas);
var imgData = canvas.toDataURL("image/jpeg",1);
var pdf = new jsPDF("p", "mm", "a4");
var pageWidth = pdf.internal.pageSize.getWidth();
var pageHeight = pdf.internal.pageSize.getHeight();
var imageWidth = canvas.width;
var imageHeight = canvas.height;
var ratio = imageWidth/imageHeight >= pageWidth/pageHeight ? pageWidth/imageWidth : pageHeight/imageHeight;
//pdf = new jsPDF(this.state.orientation, undefined, format);
pdf.addImage(imgData, 'JPEG', 0, 0, imageWidth * ratio, imageHeight * ratio);
pdf.save("invoice.pdf");
//$("#previewBeforeDownload").hide();
$('#c-invoice').modal('hide');
});
},500);
});
});
One way is to use window.print() function. Which does not require any library
Pros
1.No external library require.
2.We can print only selected parts of body also.
3.No css conflicts and js issues.
4.Core html/js functionality
---Simply add below code
CSS to
#media print {
body * {
visibility: hidden; // part to hide at the time of print
-webkit-print-color-adjust: exact !important; // not necessary use
if colors not visible
}
#printBtn {
visibility: hidden !important; // To hide
}
#page-wrapper * {
visibility: visible; // Print only required part
text-align: left;
-webkit-print-color-adjust: exact !important;
}
}
JS code - Call bewlow function on btn click
$scope.printWindow = function () {
window.print()
}
Note: Use !important in every css object
Example -
.legend {
background: #9DD2E2 !important;
}
Use pdfMake.js and this Gist.
(I found the Gist here along with a link to the package html-to-pdfmake, which I end up not using for now.)
After npm install pdfmake and saving the Gist in htmlToPdf.js I use it like this:
const pdfMakeX = require('pdfmake/build/pdfmake.js');
const pdfFontsX = require('pdfmake-unicode/dist/pdfmake-unicode.js');
pdfMakeX.vfs = pdfFontsX.pdfMake.vfs;
import * as pdfMake from 'pdfmake/build/pdfmake';
import htmlToPdf from './htmlToPdf.js';
var docDef = htmlToPdf(`<b>Sample</b>`);
pdfMake.createPdf({content:docDef}).download('sample.pdf');
Remarks:
My use case is to create the relevant html from a markdown document (with markdown-it) and subsequently generating the pdf, and uploading its binary content (which I can get with pdfMake's getBuffer() function), all from the browser. The generated pdf turns out to be nicer for this kind of html than with other solutions I have tried.
I am dissatisfied with the results I got from jsPDF.fromHTML() suggested in the accepted answer, as that solution gets easily confused by special characters in my HTML that apparently are interpreted as a sort of markup and totally mess up the resulting PDF.
Using canvas based solutions (like the deprecated jsPDF.from_html() function, not to be confused with the one from the accepted answer) is not an option for me since I want the text in the generated PDF to be pasteable, whereas canvas based solutions generate bitmap based PDFs.
Direct markdown to pdf converters like md-to-pdf are server side only and would not work for me.
Using the printing functionality of the browser would not work for me as I do not want to display the generated PDF but upload its binary content.
I was able to get jsPDF to print dynamically created tables from a div.
$(document).ready(function() {
$("#pdfDiv").click(function() {
var pdf = new jsPDF('p','pt','letter');
var specialElementHandlers = {
'#rentalListCan': function (element, renderer) {
return true;
}
};
pdf.addHTML($('#rentalListCan').first(), function() {
pdf.save("caravan.pdf");
});
});
});
Works great with Chrome and Firefox... formatting is all blown up in IE.
I also included these:
<script src="js/jspdf.js"></script>
<script src="js/jspdf.plugin.from_html.js"></script>
<script src="js/jspdf.plugin.addhtml.js"></script>
<script src="//mrrio.github.io/jsPDF/dist/jspdf.debug.js"></script>
<script src="http://html2canvas.hertzen.com/build/html2canvas.js"></script>
<script type="text/javascript" src="./libs/FileSaver.js/FileSaver.js"></script>
<script type="text/javascript" src="./libs/Blob.js/Blob.js"></script>
<script type="text/javascript" src="./libs/deflate.js"></script>
<script type="text/javascript" src="./libs/adler32cs.js/adler32cs.js"></script>
<script type="text/javascript" src="js/jspdf.plugin.addimage.js"></script>
<script type="text/javascript" src="js/jspdf.plugin.sillysvgrenderer.js"></script>
<script type="text/javascript" src="js/jspdf.plugin.split_text_to_size.js"></script>
<script type="text/javascript" src="js/jspdf.plugin.standard_fonts_metrics.js"></script>
If you want to export a table, you can take a look at this export sample provided by the Shield UI Grid widget.
It is done by extending the configuration like this:
...
exportOptions: {
proxy: "/filesaver/save",
pdf: {
fileName: "shieldui-export",
author: "John Smith",
dataSource: {
data: gridData
},
readDataSource: true,
header: {
cells: [
{ field: "id", title: "ID", width: 50 },
{ field: "name", title: "Person Name", width: 100 },
{ field: "company", title: "Company Name", width: 100 },
{ field: "email", title: "Email Address" }
]
}
}
}
...
This example works great.
<button onclick="genPDF()">Generate PDF</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script>
function genPDF() {
var doc = new jsPDF();
doc.text(20, 20, 'Hello world!');
doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
doc.addPage();
doc.text(20, 20, 'Do you like that?');
doc.save('Test.pdf');
}
</script>
Dissatisfied with the rendering of html2canvas and lack of modern CSS3/JS and print specific CSS support of pdfMake's outdated version of WebKit...
Here's a theoretical solution, it's headless and can render pages faithfully, supports page breaks, margins, different page sizes and can be automated. You can even render WebGl to PDF.
Chrome has a devtools protocol... which has a printtoPDF function
Excerpt: https://gitlab.com/-/snippets/new
Official 20k-SLOC spec: https://github.com/ChromeDevTools/devtools-protocol/blob/master/json/browser_protocol.json
You can use node and https://github.com/GoogleChrome/chrome-launcher to run chrome headless... wait for it to render.
Profit
printToPDF command you'd run on chrome_devtools protocol:
printToPDF({
printBackground: false,
pageWidth: 8.5,
pageHeight: 11,
transferMode: "ReturnAsStream" // or ReturnAsBase64
})
2022 Answer:
To generate PDF from HTML Element and prompt to save file:
import { jsPDF } from "jsPDF"
function generatePDF() {
const doc = new jsPDF({ unit: 'pt' }) // create jsPDF object
const pdfElement = document.getElementById('pdf') // HTML element to be converted to PDF
doc.html(pdfElement, {
callback: (pdf) => {
pdf.save('MyPdfFile.pdf')
},
margin: 32, // optional: page margin
// optional: other HTMLOptions
})
}
<button onclick="generatePDF()">Save PDF</button>
...
To preview PDF without printing:
doc.html(pdfElement, {
callback: (pdf) => {
const myPdfData = pdf.output('datauristring')
}
})
<embed type="application/pdf" src={myPdfData} />
...
For more HTMLOptions:
https://github.com/parallax/jsPDF/blob/master/types/index.d.ts
To capture div as PDF you can use https://grabz.it solution. It's got a JavaScript API which is easy and flexible and will allow you to capture the contents of a single HTML element such as a div or a span
In order to implement it you will need to first get an app key and secret and download the (free) SDK.
And now an example.
Let's say you have the HTML:
<div id="features">
<h4>Acme Camera</h4>
<label>Price</label>$399<br />
<label>Rating</label>4.5 out of 5
</div>
<p>Cras ut velit sed purus porttitor aliquam. Nulla tristique magna ac libero tempor, ac vestibulum felisvulput ate. Nam ut velit eget
risus porttitor tristique at ac diam. Sed nisi risus, rutrum a metus suscipit, euismod tristique nulla. Etiam venenatis rutrum risus at
blandit. In hac habitasse platea dictumst. Suspendisse potenti. Phasellus eget vehicula felis.</p>
To capture what is under the features id you will need to:
//add the sdk
<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
//login with your key and secret.
GrabzIt("KEY", "SECRET").ConvertURL("http://www.example.com/my-page.html",
{"target": "#features", "format": "pdf"}).Create();
</script>
Please note the target: #feature. #feature is you CSS selector, like in the previous example. Now, when the page is loaded an image screenshot will now be created in the same location as the script tag, which will contain all of the contents of the features div and nothing else.
The are other configuration and customization you can do to the div-screenshot mechanism, please check them out here
The following method works fine for my case.
Hide additional parts for a page like the following example
#media print{
body{
-webkit-print-color-adjust: exact; // if you want to enable graphics
color-adjust: exact !important; // if you want to enable graphics
print-color-adjust: exact !important; // if you want to enable graphics
* {
visibility: hidden;
margin:0;
padding:0
}
.print_area, .print_area *{
visibility: visible;
}
.print_area{
margin: 0;
align: center;
}
.pageBreak {
page-break-before : always; // If you want to skip next page
page-break-inside: avoid; // If you want to skip next page
}
}
#page {
size: A4; margin:0mm; // set page layout
background-color: #fff;
}
}
Use the javascript print function to print execution.
<button onclick="window.print()">Print</button>
any one try this
(function () {
var
form = $('.form'),
cache_width = form.width(),
a4 = [595.28, 841.89]; // for a4 size paper width and height
$('#create_pdf').on('click', function () {
$('body').scrollTop(0);
createPDF();
});
//create pdf
function createPDF() {
getCanvas().then(function (canvas) {
var
img = canvas.toDataURL("image/png"),
doc = new jsPDF({
unit: 'px',
format: 'a4'
});
doc.addImage(img, 'JPEG', 20, 20);
doc.save('Bhavdip-html-to-pdf.pdf');
form.width(cache_width);
});
}
// create canvas object
function getCanvas() {
form.width((a4[0] * 1.33333) - 80).css('max-width', 'none');
return html2canvas(form, {
imageTimeout: 2000,
removeContainer: true
});
}
}());

How to load a GV file in d3-graphviz?

I am trying to visualise a GV file with D3-Graphviz library. I have called the GV file directly in my code:
<script src="https://unpkg.com/#hpcc-js/wasm#0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz#3.0.5/build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
let dots = new FileReader();
dots.readAsText('G.gv')
let dotIndex = 0;
let graphviz = d3.select("#graph").graphviz()
.transition(function () {
return d3.transition("main")
.ease(d3.easeLinear)
.delay(500)
.duration(1500);
})
.logEvents(true)
.on("initEnd", render);
function render() {
var dotLines = dots[dotIndex];
var dot = dotLines.join('');
graphviz
.addImage("images/Officer.png", "50px", "50px")
.addImage("images/Manager.png", "50px", "50px")
.addImage("images/Employee.png", "50px", "50px")
.addImage("images/Service.png", "50px", "50px")
.renderDot(dot);
}
My GV file currently looks like this:
digraph G {
graph [center=true rankdir=LR ratio=compress size="15,10"]
"MainOfficer" [label="MainOfficer" fontsize=10 image="images/MainOfficer.png" shape=plaintext]
"Employee" [label="MainOfficer" fontsize=10 image="images/Employee.png" shape=plaintext]
"Supporter" [label="MainOfficer" fontsize=10 image="images/Manager.png" shape=plaintext]
}
However, when I opened the HTML file, no graph is shown, and when I checked into the console the error is Failed to execute ReadAsText as parameter 1 is not of type "Blob".
I have tried multiple ways to load the G.gv file into the website (from converting it into text and parse to the Javascript code, to rendering GV file to SVG), however none of my approach worked.
So I would like to ask that is there anyway I could load a GV file to d3-Graphviz, so that my graph could be shown without my need to paste the GV file content directly to the Javascript file?
Thank you!

html2canvas works on jsfiddle but doesn't work on my site

based on https://jsfiddle.net/Sq7hg/3120/
it's pure JS - without any library - but it works on jsfiddle
on my site - and also here - it doesn't work
I'm getting error - html2canvas is not defined
please help
html2canvas([document.getElementById('mydiv')], {
onrendered: function (canvas) {
document.getElementById('canvas').appendChild(canvas);
var data = canvas.toDataURL('image/png');
var image = new Image();
image.src = data;
document.getElementById('image').appendChild(image);
}
});
#mydiv {
background-color: lightblue;
width: 100px;
height: 100px
}
<div id="mydiv"><p>text!</p></div>
<br><br>
<div id="canvas"><p>Canvas:</p></div>
<div id="image"><p>Image:</p></div>
it seems that you are not importing html2canvas anywhere. You can have a look at the docs and follow along.
You will need to add an import in your js.
import html2canvas from 'html2canvas';
As the docs state, this is if you installed it via npm in your project.

Downloading a qrcode.js-generated QR code

I've searched the web countless times trying to find a way to solve this but I've come up empty-handed every time. I have been using qrcode.js to generate QR codes for a website, but I haven't figured out how to download the image once it's been generated. The code I use to generate the QR code looks like this:
var myQR = new QRCode(document.getElementById("qrcode"), {
text: "Made with QR Generator",
width: 128,
height: 128,
colorDark : qrdarkcolor,
colorLight : qrlightcolor,
correctLevel : QRCode.CorrectLevel.H
});
myQR.makeCode(qrdata);
I am trying to find a way to either download the QR code within the div or find the source and create a button that users can click on to download the image. I apologize if this is a commonly asked question, but I've searched many other questions that are similar to this and haven't found a clear answer. I would prefer to keep this site with only HTML, CSS, and Javascript if possible.
Thanks!
The image is generated through the plugin and takes a moment to render, so the method needs to be done with setTimeout. After that, we grab the src of the image and apply it to a download link (a link that has the attribute download in it)
Note this won't work in the snippet sandbox, but it's been tested on a normal web page and works great.
const makeQR = (url, filename) => {
var qrcode = new QRCode("qrcode", {
text: "http://jindo.dev.naver.com/collie",
width: 128,
height: 128,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
qrcode.makeCode(url);
setTimeout(() => {
let qelem = document.querySelector('#qrcode img')
let dlink = document.querySelector('#qrdl')
let qr = qelem.getAttribute('src');
dlink.setAttribute('href', qr);
dlink.setAttribute('download', 'filename');
dlink.removeAttribute('hidden');
}, 500);
}
makeQR(document.querySelector('#text').value, 'qr-code.png')
#qrcode {
width: 160px;
height: 160px;
margin-top: 15px;
}
<script src="https://cdn.jsdelivr.net/npm/davidshimjs-qrcodejs#0.0.2/qrcode.min.js"></script>
<input id="text" type="text" value="https://stackoverflow.com" style="width:80%" /><br />
<div id="qrcode"></div>
<a id='qrdl' hidden>Download</a>
You can use Qurious to generate QR code in canvas and then download it. Qurious has also its own padding option (it makes white borders around the qr code so it's possible to scan it after download).
Add this at the <head> part:
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrious/4.0.2/qrious.min.js"></script>
Html body:
<canvas id="qrcode"></canvas>
Script:
const makeQR = (your_data) => {
let qrcodeContainer = document.getElementById("qrcode");
qrcodeContainer.innerHTML = "";
new QRious({
element: qrcodeContainer,
value: your_data,
size: 600,
padding:50,
}); // generate QR code in canvas
downloadQR(); // function to download the image
}
function downloadQR() {
var link = document.createElement('a');
link.download = 'filename.png';
link.href = document.getElementById('qrcode').toDataURL()
link.click();
}
makeQR("Your value")
I noticed that the 'qrcodejs' is returning img with blank src on mobile device browsers(Android -> Chrome), whereas it returns an img with valid src (data URI) when you request from mobile as a 'desktop agent'.
You could able to test it by debugging the mobile.

Javascript causes Chromium to run out of memory

I have a chunk of code that causes a graph that monitors a graph to update periodically and is displayed with a raspberry pi, but the problem I'm having is because of the Pi's limited memory, Chromium dies because it run out of memory. I think this is because when the image updates, it saves the older images somewhere. I've tried using JS to delete the image and create a new one with an updated image, but it didn't work. I'm not too familiar with Javascript so I wasn't sure if I was making a rookie mistake or something. Here is the code:
<script type= "text/javascript">
var graph = "http://www.example.com";
function preload()
{
try
{
var buffer = new Image();
buffer.src = graph;
buffer.onload = function()
{
while (1)
{
setTimeout(preload, 1000);
document.getElementById('graph').src = buffer.src;
}
}
}
catch(err)
{
txt = "Error\n" + err.message;
alert(txt);
}
}
preload()
</script>
And the HTML for the image is:
<img src= "http://www.example.com" id=graph width=1015
height=275 frameborder="0" onload="preload()" style="display: block;
margin-left: auto; margin-right: auto;" align="bottom"/>
Here is a vastly simplified script for you - your loop made no sense at all and there is no Ajax in your code
var graph = "https://zabbix.tulsahpc.org/signage/sign.png",tId;
window.onload=function() {
tId=setInterval(function() {
document.getElementById('graph').src = graph+new Date().getTime();// avoid cache
},10000);// reload every 10 secs
}

Categories

Resources