html element caputre using html2canvas error - javascript

Hi I'm making a code using mediapipe javascript and I want to capture the output canvas
which has the landmarks and line, so I'm trying to use html2canvas but I'm having some errors could you guys help me or give me other solutions? As a result I want the capture the image and store it in sessionStorage or firestore and show it on the next html page.
This is the part where the html elements are.
the output_canvas is where the mediapipe landmarks are shown.
When I run this code I get the error of typeerror: cannot read properties of undefined (reading 'toDataURL')
<body>
<div class="container">
<div class = "ui-element" id="angle21"></div>
<div class="ui-element" id = "clock"></div>
<div class="ui-element" id = "clock2"></div>
<video class="input_video"></video>
<canvas class="output_canvas" width="1280px" height="720px"></canvas>
<div class="landmark-grid-container"></div>
</div>
</body>
And this is the script part where I use the html2canvas
const takeScreenShot = async () => {
//const screenshotTarget = document.body;
var screenshotTarget = document.querySelector('.output_canvas');
// document.querySelectorAll('.ui-element').forEach(element => {
// element.style.display = 'none'
// })
//var screenshotTarget=document.querySelector('.output_canvas');
const canvas = html2canvas(screenshotTarget, {
allowTaint:true,
foreignObjectRendering: true
});
console.log(canvas)
const base64image = canvas[1].toDataURL();
window.location.href = base64image;
// document.querySelectorAll('.ui-element').forEach(element => {
// element.style.display = 'block'
// })
}
setTimeout(async () => {
await takeScreenShot()
}, 1000 * 8)

Related

Using html2canvas action is working just once and i need the code works multiple times

im creating a web app using some html2canvas, the idea is: an user uploads a photo then choose a png image from a library to place over the image and the the user can download the image with the sticker aplied. Everything is working fine the first time, but when i try to use the download button a second time nothing happens. The console shows the following error:
Uncaught TypeError: Cannot set property 'id' of null at HTMLButtonElement.capture (index.html:82)
The line number 82 is: body.id = 'CapturaPantalla';
How could i reset the code everytime so the user could download the image multiple times?
This is the code:
<script>
const capture = () => {
const body = document.querySelector('#ImagenLista');
body.id = 'CapturaPantalla';
html2canvas(document.querySelector("#CapturaPantalla")).then(canvas => {
document.body.appendChild(canvas);
}).then(() => {
var canvas = document.querySelector('canvas');
canvas.style.display = 'none';
var image = canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream");
var a = document.createElement("a");
a.setAttribute('download', 'YoSoyYVoyA.jpg');
a.setAttribute('href', image);
a.click();
});
};
const btn = document.getElementById('DescargaImagen');
function FuncionDescarga() {
btn.addEventListener('click', capture);
}
</script>
Thanks everyone in advance.
First, you are getting an element:
const body = document.querySelector('#ImagenLista');
Then, you change the ID of the element:
body.id = 'CapturaPantalla';
So when you go to select the element again, it has a different ID, therefore returning null.
The solution should be obvious, but if for some reason you have to keep line 82, you can do this:
if (body) {
body.id = 'CapturaPantalla';
}
And a more compressed version:
body && (body.id = 'CapturaPantalla');

Check if html tag contains text node

I have a popup modal in Shopify, I'm using text node instead of innerHtml for security concerns. However, everytime I open the popup modal, the text node keeps getting appended to my h1 tag. Is there any way to check if the node already has been appended? (I don't want to use a boolean value to check if text node has been appended)
html:
<h1 id="ProductHeading" class="product__title product__title--template"></h1>
<h2 id="ProductHeadingModal" class="product__title product__title--template product__title--modal"></h2>
javascript:
var title = document.createTextNode(product.title);
// Product heading is an element with h1 tag
var productHeading = document.getElementById("ProductHeading");
if(// how to check if element has no node?) {
productHeading.appendChild(title);
}
the entire javascript block:
window.onload = () => {
if (window.__shgProductInits.length) {
window.__shgProductInits.forEach((ele) => {
let proId = document.getElementById(ele.uuid);
proId.setAttribute('url', ele.productHandle);
proId.style.cursor='pointer';
proId.addEventListener('click', (e) => {
let productHandle = e.target.parentElement.parentElement.parentElement.getAttribute('url');
fetch('/products/'+productHandle+'.js')
.then((res) =>{return res.json()})
.then((product) => {
console.log(product)
var product = product;
document.getElementsByClassName("product-modal")[0].style.display = "block";
var title = document.createTextNode(product.title);
var productHeading = document.getElementById("ProductHeading");
var productHeadingModal = document.getElementById("ProductHeadingModal");
if(!(productHeading.hasChildNodes())) {
productHeading.appendChild(title);
productHeadingModal.appendChild(title);
var price = document.createTextNode("$" + parseInt(product.price).toFixed(2));
document.getElementById("product-price").appendChild(price);
}
document.getElementById("product-image").src = product.images[0];
});
});
});
}
ProductHeading itself is not a node (I think). And checking innerHtml for length doesn't work as it is always 0
Update:
I've added the conditional check, it still returns false everytime I open the modal.
My code:
My browser console:
My website displays:
Inspect element in browser:
A couple of ways:
if (element.firstChild) {
// It has at least one
}
or the hasChildNodes() function:
if (element.hasChildNodes()) {
// It has at least one
}
or the length property of childNodes:
if (element.childNodes.length > 0) { // Or just `if (element.childNodes.length)`
// It has at least one
}
So you can just write this
var title = document.createTextNode(product.title);
// Product heading is an element with h1 tag
var productHeading = document.getElementById("ProductHeading");
if(!(productHeading.hasChildNodes())) {
productHeading.appendChild(title);
}
Referring this answer
if (productHeading.hasChildNodes()) {
}

How can I swap between two images on infinite clicks?

How can I swap between two images on infinite clicks (not once) using JS or jQuery
$("button").click(function(){
$("img").attr("src","The New SRC");
});
This code works, but just once.
Try this
var q = 0;
function swapImage() {
if (q == 0) {
document.getElementById("image").setAttribute('src', 'https://images.unsplash.com/photo-1562102010-558d6be6268e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
q++;
} else {
document.getElementById("image").setAttribute('src', 'https://images.unsplash.com/photo-1567095740613-beef70b7e61c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
q--;
}
}
<img id="image" src="https://images.unsplash.com/photo-1567095740613-beef70b7e61c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80" onclick="swapImage();" />
Let make this simple as possible swap the src and data-src on click.
$('.changeSrc').on('click', function(e){
let src2= $('#img').data('src2');
$('#img').data('src2', $('#img').attr('src'));
alert(src2);
$('#img').attr('src', src2);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img id="img" src="./images/img1.jpg" data-src2="./images/img2.jpg"/>
<button class="changeSrc">Change Picture</button>
If by "forever" you mean your user will always see the same image once he's changed it, you need to store that information somewhere. Here's an example where you store the image source in the browser's local storage and read that to set the src property of the image element:
<p>
<img id="my-img" src="">
</p>
<button onclick="changeImage()">
Change image
</button>
<script>
const myImg = document.getElementById("my-img")
const googleLogo = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
const duckduckgoLogo = "https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon#2.png"
const changeImage = () => {
if(myImg.src === googleLogo) {
myImg.src = duckduckgoLogo
localStorage.setItem("img-src", duckduckgoLogo)
} else {
myImg.src = googleLogo
localStorage.setItem("img-src", googleLogo)
}
}
const getImageSrc = () => {
const loadedSrc = localStorage.getItem("img-src")
if(loadedSrc == null) {
myImg.src = googleLogo
} else {
myImg.src = loadedSrc
}
}
getImageSrc()
</script>
Note: The code is correct but it doesn't work in the snippet because I'm reading from localStorage and this seems to be not allowed inside a snippet.

Why is clientHeight of images 0 after creating array from HTMLCollection?

So im performing a GET request to unsplash to load images on a page. I want to get the clientHeight of the loaded images so I can manipulate CSS grid span properties on each one. I'm able to get the images and their clientHeights, but when I use Array.from to make an array from the HTMLCollection, the items in the new array have a clientHeight of 0 and im not sure why. I appreciate any help!
Here's my full JS code:
axios
.get('https://api.unsplash.com/photos/random', {
params: { count: 5 },
headers: {
Authorization: `Client-ID ${ID}`
}
})
.then(response => {
let html = '';
response.data.forEach(image => {
html += `
<img src=${image.urls.regular} alt=${
image.alt_description
} />
`;
});
document.getElementById('posts').innerHTML = html;
updateHTML();
});
const updateHTML = () => {
let postsHTML = document.getElementsByTagName('img');
console.log(postsHTML);
let postsArray = Array.from(postsHTML);
console.log(postsArray);
let html = '';
postsArray.map(post => {
console.log(post.clientHeight);
const span = setSpans(post.clientHeight);
html += `
<img src=${post.src} alt=${
post.alt
} style="grid-row-end: span ${span}"/>
`;
});
console.log(html);
document.getElementById('posts').innerHTML = html;
};
const setSpans = height => {
return Math.ceil(height / 10 + 1);
};
Your images are still in loading state, you can't get the right clientHeight. You need to handle the onload event of images and then query the clientHeight.

onclick function not working in JS

New here. I'm trying to use onclick to switch out some images that i have assigned to variables in my script but i can't get it to work. Any ideas?
let doorImage1 = document.getElementById("door1");
let botDoorPath ='https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg';
doorImage1.onclick= () =>{
doorImage1.src = botDoorPath;
}
This did not work for me until I set the src in the element to something first. Seems to be working, so perhaps your element was not found. Look at console to see if it was undefined.
let doorImage1 = document.getElementById("door1");
let botDoorPath = 'https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg';
doorImage1.onclick = () => {
console.log('click')
doorImage1.src = botDoorPath;
}
<html>
<img src='./missing.png' id='door1'></img>
</html>

Categories

Resources