I'm working on a little card creator. The idea behind it, is to take data from a CSV, accordingly get some images from a folder, put them into a canvas with the related text (name, power, bonus etc) and then save it as images (would be awesome if filename = cardname.jpg). But I'm actually stucked with getting the download working properly. The main problem is that every solution I tried, gives me back a blank jpeg, with no trace of my filled canvas. The second problem is that I don't want the download event to be triggered by a button. Just pick the CSV, upload it, let the code create a canvas for each card and download each card in the same folder without any need for confirmation. Is it possible?
The CSV structure is easy, just a lot of rows with the same pattern: ClanName,CardName,1,1,1,CardPower,CardBonus,FullName
The Papaparse library is handled by the two filed I got from their site, as I did not find any CDN.
I'm a beginner, so the easiest the answer the better it is. The important point is to have every img, saved as a jpg inside the same folder. (For example: C:\Users\MyName\Desktop\CardCollectionFolder)
The code is meant to be run once, just to create the bulk of cards as jpegs, offline and on my own computer. So, no security issues within.
Here my code (HTML/CSS + JS/JQuery)
$( document ).ready(function() {
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function creaCartaFinale(results, i){
var canvas = document.getElementById("myCanvas"+i);
var context = canvas.getContext('2d');
var clan=(results.data[i][0]);
const nome =(results.data[i][1]);
var rarita =(results.data[i][2]);
var stelle =(results.data[i][3]);
var potenza =(results.data[i][4]);
var danno =(results.data[i][5]);
const potere =(results.data[i][6]);
const bonus=(results.data[i][7]);
var nomeintero=(results.data[i][8]);
imgStelle = "Immagini/LivelloCarte/livello"+ stelle +".png";
imgClan= "Immagini/IconeClan/"+ clan +"_42.png";
if (rarita=="Non comune"){
imgRarita = "Immagini/RaritaCarta/raritanoncomune.png";
} else {
imgRarita = "Immagini/RaritaCarta/rarita"+rarita+".png";
}
immagine ="Immagini/ImmaginiChar/"+clan+"_"+nomeintero+"_N"+stelle+"_HD_673.png"
var sources = {
image1: 'Immagini/SfondoCarte/base.png',
image2:'Immagini/SfondoCarte/riquadro.png',
image3: immagine,
image4:'Immagini/SfondoCarte/poteri.png',
image5: imgRarita,
image6: imgStelle,
image7: 'Immagini/SfondoCarte/riquadrobis.png',
image8: imgClan,
image9: 'Immagini/Numeri/'+potenza+'.png',
image10:'Immagini/Numeri/'+danno+'.png',
};
loadImages(sources, function(images) {
context.drawImage(images.image1, 0, 0, 2220 , 3240); //SFONDO * x - y
context.drawImage(images.image2, 80, 80, 2040 ,1900);//RIQUADRO
context.drawImage(images.image3, 0, 0, 2220 ,3150); //IMMAGINE *
context.drawImage(images.image4, 80, 2000, 2050 ,1150); //LAYOUT POTERI *
context.drawImage(images.image5, 520, 80, 1610 ,200); //RARITA *
context.drawImage(images.image6, 600, 2000, 1240 ,260); //STELLE *
context.drawImage(images.image7, 100, 70, 360 ,360); //RIQUADRO CLAN *
context.drawImage(images.image8, 120, 80, 320 ,320); //CLAN *
context.drawImage(images.image9, 170, 2350, 130 ,170); //FORZA *
context.drawImage(images.image10, 170, 2950, 130 ,170); //DANNO *
//STAMPA NOME
context.font = "200px Calibri";
var gradient = context.createLinearGradient (0,0, canvas.width,0)
gradient.addColorStop("0", "white")
context.fillStyle = gradient;
context.fillText(nome, 600, 250);
//STAMPA POTERI E BONUS
context.font = "105px Calibri";
if (potere.length > 34){
var ultimoIndice = potere.length -1;
var frase30 = potere.slice(0,33);
var n = frase30.lastIndexOf(" ");
var primaFrase = potere.slice(0,n)
var secondaFrase = potere.slice(n,ultimoIndice)
context.fillText(primaFrase, 750, 2500);
context.fillText(secondaFrase, 750, 2620);
}
else{
context.fillText(potere, 750, 2500);
}
if (bonus.length > 34){
var ultimoIndice = bonus.length -1;
var frase30 = bonus.slice(0,33);
var n = frase30.lastIndexOf(" ");
var primaFrase = bonus.slice(0,n)
var secondaFrase = bonus.slice(n,ultimoIndice)
context.fillText(primaFrase, 750, 2850);
context.fillText(secondaFrase, 750, 2970);
}
else{
context.fillText(bonus,750, 2850);
}
});
}
document.getElementById('txtFileUpload').addEventListener('change', upload, false);
function upload(evt) {
var file = evt.target.files[0];
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function (event) {
var csvData = event.target.result;
Papa.parse(csvData, {
complete: function (results) {
console.log(results.data);
var numeroCarte=(results.data.length);
for(var i=0; i<numeroCarte; i++){
$( ".cartaSingola" ).prepend( "<canvas class='cardCanvas' id='myCanvas"+i+"' width='2500' height='3500'></canvas>" );
creaCartaFinale(results,i);
download_image(i);
}
}
});
};
}
//THIS FUNCTION DOES NOT WORK, JUST GIVES BACK A BLANK FILE
function download_image(i){
var canvas = document.getElementById("myCanvas"+i);
image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
var link = document.createElement('a');
link.download = "my-image.png";
link.href = image;
link.click();
}
});
/* .contenitoreCarte{
height:88mm;
width:63mm;
} */
.cartabase{
margin:15px;
height:88mm;
width:63mm;
}
.nomeCarta{
position: relative;
top: -352px;
right: -102px;
width:45mm;
height:6mm;
text-align: center;
z-index:1;
}
.nomeCarta p{
text-align: center;
width: 100%;
left: -32px;
position: relative;
}
.potereCarta{
position: relative;
top: -352px;
right: -102px;
width:45mm;
height:6mm;
text-align: center;
}
.potereCarta p{
text-align: center;
position: relative;
bottom: -194px;
width: 82%;
left: -6px;
word-wrap: break-word
}
.bonusCarta{
position: relative;
top: -352px;
right: -102px;
width:45mm;
height:6mm;
text-align: center;
}
.bonusCarta p{
text-align: center;
width: 82%;
left: -6px;
bottom: -195px;
position: relative;
word-wrap: break-word
}
.forzaCarta{
position: relative;
top: -352px;
right: -102px;
width:45mm;
height:6mm;
text-align: center;
}
.forzaCarta p{
text-align: center;
width: 100%;
left: -148px;
bottom: -119px;
position: relative;
}
.dannoCarta{
position: relative;
top: -352px;
right: -100px;
width:45mm;
height:6mm;
text-align: center;
}
.dannoCarta p{
text-align: center;
width: 100%;
left: -146px;
bottom: -139px;
position: relative;
}
.livelloCarta{
/* width: 32mm; */
width: 42mm;
height: 7mm;
right: -36px;
top: -166px;
position: relative;
}
.clanCarta{
height: 9mm;
width: 9mm;
right: -15px;
top: -278px;
position: relative;
z-index: 1;
}
.raritaCarta{
height: 6mm;
width: 45mm;
right: -35px;
top: -296px;
position: relative;
}
.baseCarta{
height: 88mm;
width: 63mm;
right: -7px;
top: -312px;
position: relative;
z-index: -99;
}
.riquadroCarta{
height: 50mm;
width: 56mm;
right: -14px;
top: -473px;
position: relative;
}
.poteriCarta{
height: 32mm;
width: 58mm;
right: -12px;
top: -470px;
position: relative;
z-index: -99;
}
.immaginiCarta{
height: 92mm;
width: 68mm;
right: -3px;
top: -642px;
position: relative;
z-index: 1;
}
.cardCanvas{
position: relative;
display: block;
}
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet"type="text/css" />
<link rel="stylesheet" href="Pagina.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="Pagina.js"></script>
<script src="papaparse.js"></script>
<script src="papaparse.min.js"></script>
<title>Card maker</title>
</head>
<body>
<input type="file" name="File Upload" id="txtFileUpload" accept=".csv" />
<div class="cartaSingola">
</div>
</body>
</html>