From 5421a80fb39a32395f6f5468bf5ac069835fa854 Mon Sep 17 00:00:00 2001
From: anthony-zhou <37421108+anthony-zhou@users.noreply.github.com>
Date: Wed, 11 Dec 2019 12:23:13 -0600
Subject: [PATCH] Add Save as PDF option (#1349)
* Add Save as PDF option
* Edit coments for consistency
Edits follow the JSDoc guidelines. Comments begin with a capital letter and end with a period.
---
examples/demo.js | 40 +++++++++++
examples/index.html | 6 +-
package-lock.json | 165 +++++++++++++++++++++++++++++++++++++++++++-
package.json | 1 +
4 files changed, 209 insertions(+), 3 deletions(-)
diff --git a/examples/demo.js b/examples/demo.js
index 71dff12c..75c71f31 100644
--- a/examples/demo.js
+++ b/examples/demo.js
@@ -115,6 +115,8 @@ window.onload = function () {
}
else if (dropDownValue == 'save-seq') {
saveSequence();
+ } else if(dropDownValue == 'save-pdf') {
+ savePDF(getLastImage());
}
});
@@ -207,6 +209,44 @@ window.onload = function () {
});
}
+ /**
+ * Get the data URL for the last image in the sequence.
+ * @return {string} The data URL for the last image in the sequence.
+ */
+ function getLastImage() {
+ // Get the image from the last step.
+ let imgs = document.getElementsByClassName('step-thumbnail');
+ let lastStepImage = imgs[imgs.length-1];
+ return lastStepImage.getAttribute("src");
+ }
+
+ /**
+ * Download the given image URL as a PDF file.
+ * @param {string} imageDataURL - The data URL for the image.
+ */
+ function savePDF(imageDataURL) {
+ sequencer.getImageDimensions(imageDataURL, function(dimensions) {
+ // Get the dimensions of the image.
+ let pageWidth = dimensions.width;
+ let pageHeight = dimensions.height;
+
+ // Create a new pdf with the same dimensions as the image.
+ const pdf = new jsPDF({
+ orientation: pageHeight > pageWidth ? "portrait": "landscape",
+ unit: "px",
+ format: [pageHeight, pageWidth]
+ });
+
+ // Add the image to the pdf with dimensions equal to the internal dimensions of the page.
+ pdf.addImage(imageDataURL, 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight());
+
+ // Save the pdf with the filename specified here:
+ pdf.save("index.pdf");
+ });
+ }
+
+
+
function downloadGif(image) {
download(image, 'index.gif', 'image/gif');// downloadjs library function
}
diff --git a/examples/index.html b/examples/index.html
index 29c228b5..75b94570 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -33,7 +33,10 @@
-
+
+
+
+
@@ -190,6 +193,7 @@
diff --git a/package-lock.json b/package-lock.json
index 5e6215d1..2b0a5956 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -803,8 +803,7 @@
"base64-arraybuffer": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
- "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
- "dev": true
+ "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
},
"base64-img": {
"version": "1.0.4",
@@ -1830,6 +1829,108 @@
"map-obj": "^1.0.0"
}
},
+ "canvg": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/canvg/-/canvg-1.5.3.tgz",
+ "integrity": "sha512-7Gn2IuQzvUQWPIuZuFHrzsTM0gkPz2RRT9OcbdmA03jeKk8kltrD8gqUzNX15ghY/4PV5bbe5lmD6yDLDY6Ybg==",
+ "requires": {
+ "jsdom": "^8.1.0",
+ "rgbcolor": "^1.0.1",
+ "stackblur-canvas": "^1.4.1",
+ "xmldom": "^0.1.22"
+ },
+ "dependencies": {
+ "abab": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
+ "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4="
+ },
+ "acorn": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz",
+ "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc="
+ },
+ "acorn-globals": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz",
+ "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=",
+ "requires": {
+ "acorn": "^2.1.0"
+ }
+ },
+ "cssstyle": {
+ "version": "0.2.37",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz",
+ "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=",
+ "requires": {
+ "cssom": "0.3.x"
+ }
+ },
+ "jsdom": {
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-8.5.0.tgz",
+ "integrity": "sha1-1Nj12/J2hjW2KmKCO5R89wcevJg=",
+ "requires": {
+ "abab": "^1.0.0",
+ "acorn": "^2.4.0",
+ "acorn-globals": "^1.0.4",
+ "array-equal": "^1.0.0",
+ "cssom": ">= 0.3.0 < 0.4.0",
+ "cssstyle": ">= 0.2.34 < 0.3.0",
+ "escodegen": "^1.6.1",
+ "iconv-lite": "^0.4.13",
+ "nwmatcher": ">= 1.3.7 < 2.0.0",
+ "parse5": "^1.5.1",
+ "request": "^2.55.0",
+ "sax": "^1.1.4",
+ "symbol-tree": ">= 3.1.0 < 4.0.0",
+ "tough-cookie": "^2.2.0",
+ "webidl-conversions": "^3.0.1",
+ "whatwg-url": "^2.0.1",
+ "xml-name-validator": ">= 2.0.1 < 3.0.0"
+ }
+ },
+ "parse5": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz",
+ "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ="
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "stackblur-canvas": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-1.4.1.tgz",
+ "integrity": "sha1-hJqm+UsnL/JvZHH6QTDtH35HlVs="
+ },
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
+ },
+ "webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
+ },
+ "whatwg-url": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-2.0.1.tgz",
+ "integrity": "sha1-U5ayBD8CDub3BNnEXqhRnnJN5lk=",
+ "requires": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "xml-name-validator": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz",
+ "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU="
+ }
+ }
+ },
"cardinal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz",
@@ -2370,6 +2471,14 @@
"integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
"dev": true
},
+ "css-line-break": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-1.0.1.tgz",
+ "integrity": "sha1-GfIGOjPpX7KDG4ZEbAuAwYivRQo=",
+ "requires": {
+ "base64-arraybuffer": "^0.1.5"
+ }
+ },
"cssauron": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
@@ -4011,6 +4120,10 @@
"utils-extend": "^1.0.6"
}
},
+ "file-saver": {
+ "version": "github:eligrey/FileSaver.js#e865e37af9f9947ddcced76b549e27dc45c1cb2e",
+ "from": "github:eligrey/FileSaver.js#1.3.8"
+ },
"file-system": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/file-system/-/file-system-2.2.2.tgz",
@@ -6110,6 +6223,14 @@
}
}
},
+ "html2canvas": {
+ "version": "1.0.0-alpha.12",
+ "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-alpha.12.tgz",
+ "integrity": "sha1-OxmS48mz9WBjw1/WIElPN+uohRM=",
+ "requires": {
+ "css-line-break": "1.0.1"
+ }
+ },
"htmlescape": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
@@ -7322,6 +7443,26 @@
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
"dev": true
},
+ "jspdf": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-1.5.3.tgz",
+ "integrity": "sha512-J9X76xnncMw+wIqb15HeWfPMqPwYxSpPY8yWPJ7rAZN/ZDzFkjCSZObryCyUe8zbrVRNiuCnIeQteCzMn7GnWw==",
+ "requires": {
+ "canvg": "1.5.3",
+ "file-saver": "github:eligrey/FileSaver.js#1.3.8",
+ "html2canvas": "1.0.0-alpha.12",
+ "omggif": "1.0.7",
+ "promise-polyfill": "8.1.0",
+ "stackblur-canvas": "2.2.0"
+ },
+ "dependencies": {
+ "omggif": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.7.tgz",
+ "integrity": "sha1-WdLuywJj3oRjWz/riHwMmXPx5J0="
+ }
+ }
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -8567,6 +8708,11 @@
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
+ "nwmatcher": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",
+ "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ=="
+ },
"nwsapi": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz",
@@ -9413,6 +9559,11 @@
}
}
},
+ "promise-polyfill": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.0.tgz",
+ "integrity": "sha512-OzSf6gcCUQ01byV4BgwyUCswlaQQ6gzXc23aLQWhicvfX9kfsUiUhgt3CCQej8jDnl8/PhGF31JdHX2/MzF3WA=="
+ },
"proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@@ -10067,6 +10218,11 @@
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
},
+ "rgbcolor": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
+ "integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0="
+ },
"rimraf": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
@@ -10971,6 +11127,11 @@
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
"dev": true
},
+ "stackblur-canvas": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.2.0.tgz",
+ "integrity": "sha512-5Gf8dtlf8k6NbLzuly2NkGrkS/Ahh+I5VUjO7TnFizdJtgpfpLLEdQlLe9umbcnZlitU84kfYjXE67xlSXfhfQ=="
+ },
"static-extend": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
diff --git a/package.json b/package.json
index e2c5ef06..e56d48a8 100644
--- a/package.json
+++ b/package.json
@@ -57,6 +57,7 @@
"jasmine": "^3.4.0",
"jquery": "^3.3.1",
"jsdom": "^15.0.0",
+ "jspdf": "^1.5.3",
"jsqr": "^1.1.1",
"lodash": "^4.17.11",
"ndarray": "^1.0.18",