Saving SVG pattern as PDF and PNG - javascript

I’ve got a flowery pattern (http://pages.bangor.ac.uk/~abp4d9/) where user moves sliders (for inner circles and petals) and flowers change. I’ve got 3 ‘Save as’ buttons. 1st one (SVG) works great. The other 2 work only half-way. The saved file comes up in the appropriate format but then it doesn’t open, saying that there was an error. All 3 JS functions are almost identical – I basically copied them from the working 1st function. I’m not sure what to correct – probably ‘new Blob’ format, but I’m not sure what to put instead.
So, to sum up:
• How to get a working ‘Save as SVG’ button to do the same with PDF and PNG?
Here is my JS for half-working PDF button:
function downloadPdf(){
var svg = document.getElementsByTagName("svg")[0];
var svg_xml = (new XMLSerializer).serializeToString(svg);
var blob = new Blob([svg_xml]);
var url = window.URL || window.webkitURL;
var blobURL = url.createObjectURL(blob);
var a = document.createElement('a');
a.download = "Pattern.pdf";
a.href = blobURL;
document.body.appendChild(a);
a.click();
}

you have to create the PNG resp. PDF first. for PNG you can use canvas to draw the image and then retrieve the canvas content as PNG (or you can use a library). for PDF you have to use a library.

Related

Img src via blob/b64 does not work on iOS

I am trying to set the src of an img tag in order to display an image. The following works on android/mac/windows, but not on iOS:
let b64Bmp = pageModel.image;
this.$currentPageImage.src = `data:image/bmp;base64,${b64Bmp}`;
b64Bmp is a b64 encoded bitmap image. I also tried the same using a blob:
const blobUrl = URL.createObjectURL(resultBlob);
this.$currentPageImage.src = blobUrl;
None of these solutions work on iOS specifically. Also, when trying to create a new Image object like so:
const image = new Image();
image.src = ...
The image.onerror throws an error without any information.
What do I have to change to make this work on iOS?
Found the solution. Apparently, iOS does not display BMP files with a color depth of less than 24 bits (see https://developer.apple.com/forums/thread/715255). It works now, when sending a BMP with color depth of 24 bits

Force iOS to download image from HTML5 Canvas (using pure javascript) AND keep CSS filters applied

Reference is made to this post, which partially answered my question: Force iOS to download image from HTML5 Canvas (using pure JavaScript)
In summary, that question has been asked before and the general response is that it can't be done on iOS. However, those questions are several years old,
and the member who replied to the above question did supply a partial answer: using HTMLCanvasElement.toDataURL() to convert the image to a data URL, and then forcing the data URL to open as an image in a new tab. From there, it could then be downloaded by holding a finger on the image, opening the iOS save dialog box.
The problem is, even though my save code downloads the image with the CSS Filters applied, the image that opens in a new tab on iOS does not have the filters applied.
So, my question is, how do I take the final step: forcing the image that opens in the new tab to have the CSS Filters applied, just as a downloaded image on a computer would have the CSS Filters applied.
This is the code that takes the image from the original canvas and applies the CSS Filters, creating a new image with the CSS Filters applied:
function fileApply()
{
var cP = document.getElementById("cPreview");
var cntxCP = cP.getContext("2d");
var cS = document.getElementById("cSave");
var cntxCS = cS.getContext("2d");
// take whatever CSS filters are applied to the first canvas
var cssFilter = getComputedStyle(cP).filter;
// use those filter as the second canvas' context's filter
cS.width = cP.width;
cS.height = cP.height;
cntxCS.filter = cssFilter;
cntxCS.drawImage(cP, 0, 0);
cP.style.display = "none";
if (cS.style.display == "none") cS.style.display = "block";
}
That all works.
This is the save code:
function fileSave()
{
var canvas = document.getElementById('cSave');
if (document.getElementById("png").checked == true)
{
var quality = null; // canvas.toBlob() takes an extra argument if file type is JPG. Set quality to null to allow PNG downloads. Quality value will be supplied if JPG is selected.
var format = "image/png";
var name = "new_image.png";
}
if (document.getElementById("jpg").checked == true)
{
var format = "image/jpeg";
var quality = Number(document.getElementById("quality").value) / 100;
var name = "new_image.jpg"
}
if (!isIOS())
{
canvas.toBlob(function(blob) // Send canvas to blob and download blob
{
const anchor = document.createElement('a')
const url = URL.createObjectURL(blob)
anchor.href = url
anchor.download = name,
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
URL.revokeObjectURL(url);
}, format, quality)
}
if (isIOS())
{
var iString = canvas.toDataURL(); // convert image to base64 string
document.getElementById("iOS").innerHTML = 'click me'; // add string to url and target new tab.
}
That works fine on a computer. On iOS that creates the new image in a new tab without the CSS Filters applied.
Thank you

Attaching a user created recording to a form

I'm sure there is a super easy way to do this, but I'm pretty new to web programming so not sure of how to actually do it. I have a simple form that takes in a doc file and a media file (the media file can either be picked, or created via webcam). So far it allows the user to pick the media file or create one but I'm not sure how to attach that created file to the actual file button so it can be posted.
function sendMail(){
var blob = new Blob(recordedBlobs, {type: 'video/webm'});
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.style.display = 'none';
a.href = url;
document.getElementById("media").appendChild(a);
}
This is what I'm trying but doesn't seem to be working. ('media' is the id of my file button I want to attach the file to).

encodeURI file download - crashing browser

I created a web application to clean up CSV/TSV data. The app allows me to upload a CSV file, read it, fix data, and then download a new CSV file with the correct data. One challenge I have run into is downloading files with more than ~ 2500 lines. The browser crashes with the following error message:
"Aw, Snap! Something went wrong while displaying this webpage..."
To work around this I have changed the programming to download multiple CSV files not exceeding 2500 lines until all the data is downloaded. I would then put together the downloaded CSV files into a final file. That's not the solution I am looking for. Working with files of well over 100,000 lines, I need to download all contents in 1 file, and not 40. I also need a front-end solution.
Following is the code for downloading the CSV file. I am creating a hidden link, encoding the contents of data array (each element has 1000 lines) and creating the path for the hidden link. I then trigger a click on the link to start the download.
var startDownload = function (data){
var hiddenElement = document.createElement('a');
var path = 'data:attachment/tsv,';
for (i=0;i<data.length;i++){
path += encodeURI(data[i]);
}
hiddenElement.href = path;
hiddenElement.target = '_blank';
hiddenElement.download = 'result.tsv';
hiddenElement.click();
}
In my case the above process works for ~ 2500 lines at a time. If I attempt to download bigger files, the browser crashes. What am I doing wrong, and how can I download bigger files without crashing the browser? The file that is crashing the browser has (12,000 rows by 48 columns)
p.s. I am doing all of this in Google Chrome, which allows for file upload. So the solution should work in Chrome.
I've experienced this problem before and the solution I found was to use Blobs to download the CSV. Essentially, you turn the csv data into a Blob, then use the URL API to create a URL to use in the link, eg:
var blob = new Blob([data], { type: 'text/csv' });
var hiddenElement = document.createElement('a');
hiddenElement.href = window.URL.createObjectURL(blob);
Blobs aren't supported in IE9, but if you just need Chrome support you should be fine.
I also faced same problem. I used this code,it will works fine. You can also try this.
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(new Blob([base64toBlob($.base64.encode(excelFile), 'text/csv')]),'data.csv');
} else {
var link = document.createElement('a');
link.download = 'data.csv';
// If u use chrome u can use webkitURL in place of URL
link.href = window.URL.createObjectURL(new Blob([base64toBlob($.base64.encode(excelFile), 'text/csv')]));
link.click();
}

Unit8Array to base64 conversion and then displaying image in browser issue

I have a Unit8Array in a mongodb that represents a png image. I pull the array out and convert it to base64 using javascript (in meteor client side) so that I can display it in the browser. The code is as follows
var blob = new Uint8Array(Tester.findOne().image);
var base64String = btoa(String.fromCharCode.apply(null, blob));
var src = 'data:image/png;base64,' + base64String + '';
console.log(src);
Where Tester.findOne().image is my mongodb collection containing the Uint8Array.
I take the src once it is logged and I paste it into the browser. The generic broken image icon appears (see below). However when I click the broken image in the browser and say save to desktop, it downloads the file and when I open it the png image appears as expected.
After I Download the Image:
When I directly try to assign it to <img src = 'data'>:
Adding data as img source or by using document.findElementbyId("img") then changing img.src:

Categories