I want to make the custom element doesn’t require a div element inside, make the image’s size like the div’s size, and make the div’s bottom border appear. Also, the style element should be in the div to work, and it’s better to solve. This code works perfectly except those stuff. Simply, html2canvas is missing some elements so I remade it but with SVG.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
class CaptureElement extends HTMLElement {
capture() {
const div = this.querySelector("div");
const br = document.createElement("br");
div.appendChild(br);
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const data = new XMLSerializer().serializeToString(div);
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${div.scrollWidth}" height="${div.scrollHeight}">
<foreignObject width="100%" height="100%">
${data}
</foreignObject>
</svg>`;
const img = new Image();
img.onload = () => {
canvas.width = div.scrollWidth;
canvas.height = div.scrollHeight;
context.drawImage(img, 0, 0);
const base64 = canvas.toDataURL("image/png");
console.log(base64);
div.removeChild(br);
if (this.hasAttribute("download")) {
var filename;
const download = this.getAttribute("download");
if (!download.endsWith(".png")) {
filename = download + ".png";
}
else {
filename = download;
}
const a = document.createElement('a');
a.href = base64;
a.download = filename;
a.click();
}
};
img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);
}
}
customElements.define("capture-element", CaptureElement);
document.addEventListener("DOMContentLoaded", () => {
document.querySelector("button").addEventListener("click", () => {
document.querySelector("capture-element").capture();
})
});
</script>
<style>
button {
color: white;
background-color: gray;
border-radius: 5px;
}
div.button {
text-align: center;
}
</style>
<title>Custom element</title>
</head>
<body>
<div class="button">
<button>Download</button>
</div>
<br>
<br>
<capture-element download="Certification.png">
<div id="certification">
<style>
* {
border: 0px;
background-color: white;
font-family: "Arial";
}
h1 {
background: linear-gradient(to right bottom, rgba(255, 188, 13, 1) 23%, rgba(0, 212, 255, 1));
font-weight: lighter;
color: transparent;
background-clip: text;
text-align: center;
}
p {
margin-left: 5px;
}
div#certification {
border-top: 1px solid black;
border-right: 1px solid black;
border-left: 1px solid black;
border-bottom: 2px solid black;
border-radius: 0px;
width: 50%;
min-width: 500px;
max-width: 1000px;
margin: auto;
}
.uname {
color: transparent;
font-weight: bolder;
font-size: xx-large;
text-align: center;
margin-top: 0px;
background: linear-gradient(to right bottom, rgb(132, 160, 68) 23%, rgb(66, 171, 192));
background-clip: text;
}
.fname {
font-weight: bold;
font-size: x-large;
text-align: center;
margin-right: 150px;
margin-top: 0px;
}
div:not(#certification) {
text-align: center;
}
</style>
<h1>Digital certification</h1>
<p>This certification is made for developers, from developers. This one is specially made for:</p>
<p class="uname">Username</p>
<p>From:</p>
<p class="fname">HTML, CSS, JavaScript</p>
<div>
<ruby><meter style="font-size: xx-large;" min="0" max="100" low="33" high="66" optimum="80"></meter>
<rt style="font-size: larger;">0%</rt>
</ruby>
</div>
</div>
</capture-element>
</body>
</html>