Using socket.io, I'm pushing images from a server to the client using base64 encoded strings:
socket.on('send_picture', function (data){
socket_data = (socket_data + data);
document.getElementById('imgid').src = socket_data
})
How can I reset the src of 'imgid' at the next socket.io event? It works fine one time, but then won't display new images until I refresh the page
I've found that the most reliable way to load new image content is to create a new image element each time and replace the prior image object with the new one. You could do that like this:
socket.on('send_picture', function (data){
socket_data = socket_data + data;
var oldImg = document.getElementById('imgid');
var newImg = new Image();
newImg.src = socket_data;
newImg.id = 'imgid';
oldImg.parentNode.replaceChild(newImg, oldImg);
});
Related
I have a function that brings users to a blob when a button is clicked and selections are made. The point is for them to click a download button and it take them to a blob with the gif on the page made based off their selections. I have working js/html/css that creates and downloads the gif for them but I am trying to now make code that makes the gif appear on the blob. It is successfully taking users to the blob but the gif is not appearing on the page. Any help would be appreciated.
js for creating the gif and sending users to the blob.
var directory = '/directory/here';
// add an event listener for the 'change' event on the dropdown menu
dropdown_fg2.addEventListener('change', function() {
// check if the selectedValue1 and selectedValue2 variables have been assigned values
if (!isNaN(selectedValue1) && !isNaN(selectedValue2)) {
// create an array of images
var images = [];
// set the starting image
var startImage = selectedValue1;
// set the ending image
var endImage = selectedValue2;
// set the step size for the images
var step = 6;
// create a loop to add the images to the array
for (var i = startImage; i <= endImage; i += step) {
var filePath = directory +"gfs_6hr_2m_temp_hour_"+i+ '.png';
// add the image to the array
images.push(filePath);
}
const downloadButton = document.getElementById('download-button2');
// Handle the button click
downloadButton.addEventListener('click', function () {
/// Generate gif
gifshot.createGIF({
'images': images,
'gifWidth': 1144,
'gifHeight': 894,
'interval': 0.33
},function(obj) {
if(!obj.error) {
const reader = new FileReader();
// Read the contents of the image file as a ArrayBuffer
reader.readAsArrayBuffer(obj.image);
reader.onload = function() {
// Create a Blob object that represents the GIF file
const gifBlob = new Blob([reader.result], {type: 'image/gif'});
// Use the URL.createObjectURL() method to create a URL for the Blob
const gifUrl = URL.createObjectURL(gifBlob);
console.log(gifUrl)
window.open(gifUrl);
// You can then use the URL to open the GIF file in a new window or to display it on your website
// var animatedImage = document.createElement('img');
var animatedImage = document.getElementById('my-image')
animatedImage.src = gifUrl;
console.log(animatedImage)
}
});
});
console.log(images);
}
})
I'm pretty new to JS and programming altogether so I'm sorry in advance if the explanation is a little sloppy, but I'll try to make it as clear as possible.
So what I'm trying to do is have a JS code that reads and displays (in an HTML page) photos from a PC folder, makes them clickable and on the click it redirects you to a page with the same photo but in high resolution.
Now, I have this piece of code that displays the said pictures, but the thing is I don't seem to be able to figure out how to "connect" it to the pictures and make them clickable. What makes it more difficult is that I'm trying to make all of this code dynamic (as you can see I've done in the below code), so I would like not to have any hardcoded titles of pictures and so on.
var index = 1;
var tempImg = new Image();
tempImg.onload = function(){
appendImage();
}
var tryLoadImage = function(index){
tempImg.src = 'img/' + index + '.jpg';
}
var appendImage = function(){
var img = document.createElement('img');
img.src = tempImg.src;
document.body.appendChild(img)
tryLoadImage(index++);
}
tryLoadImage(index);
Any help is very much appreciated, thank you very much!
You can make your images clickable by adding an onclick function to them. Try something like this:
var appendImage = function(){
var img = document.createElement('img');
img.src = tempImg.src;
img.onclick = e => {
// do something you want to show the full picture like this maybe
var el = document.getElementById("fullpictureid");
if (el && e.target.src) {
el.src = e.target.src;
// so that it sets "src" in <img id="fullpictureid"> for example
}
};
document.body.appendChild(img)
tryLoadImage(index++);
}
I have created a webpage that basically displays 2 images side by side.
It has a "download" button, which triggers a vanilla Javascript function, which creates a <canvas> HTML element and concatenates the two images inside of it. It then creates a link with the base64-encoded result image as href and clicks on it:
<a download="image.png" id="dllink" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAAAMnCAYAAABhnf9DAAAgAElEQVR4nOzdR48kD3rn96j03pfv6qo21dVd3qT3JryP9Jll281..."></a>
Here is what the function I'm using looks like:
/**
* Create canvas, draw both images in it, create a link with the result
* image in base64 in the "href" field, append the link to the document,
* and click on it
*/
function saveImage() {
// Get left image
var imgLeft = new Image();
imgLeft.setAttribute('crossOrigin', 'anonymous');
imgLeft.src = "imgleft/" + idxImageShownLeft + ".jpg";
imgLeft.onload = function() {
// Once the left image is ready, get right image
var imgRight = new Image()
imgRight.setAttribute('crossOrigin', 'anonymous');
imgRight.src = "imgright/" + idxImageShownRight + ".jpg";
imgRight.onload = function() {
// Once the right image is ready, create the canvas
var canv = document.createElement("canvas");
var widthLeft = parseInt(imgLeft.width);
var widthRight = parseInt(imgRight.width);
var width = widthLeft + widthRight;
var height = imgLeft.height;
canv.setAttribute("width", width);
canv.setAttribute("height", height);
canv.setAttribute("id", "myCanvas");
canv.setAttribute('crossOrigin', 'anonymous');
var ctx = canv.getContext("2d");
// Draw both images in canvas
ctx.drawImage(imgLeft, 0, 0);
ctx.drawImage(imgRight, widthLeft, 0);
// Create PNG image out of the canvas
var img = canv.toDataURL("image/png");
// Create link element
var aHref = document.createElement('a');
aHref.href = img;
aHref.setAttribute("id", "dllink");
aHref.download = "image.png";
// Append link to document
var renderDiv = document.getElementById("render");
renderDiv.replaceChild(aHref, document.getElementById("dllink"));
// Click on link
aHref.click();
}
}
}
My problem is that this works fine on Firefox, but not on Chrome.
After a bit of investigating, I realized that by setting a breakpoint before the aHref.click(); line in Chrome, it worked fine. I think that it means that the aHref.click(); is called before the <a href="data:image/png;base64,...></a> is ready to be clicked, but I don't know for sure.
I couldn't find a duplicate of this topic. What keywords should I use just to be 100% sure?
Am I investigating in the right direction?
Is there an event I could rely on in order to call aHref.click(); only when it is ready?
You could wrap it in an init function that gets called when the window completes loading.
function init() {
aHref.click();
}
window.onload = init;
Its similar to the vanilla equivalent of jQuery's .ready() method.
aHref , document.getElementById("dllink") appear to be same element ? Though "dllink" has not yet been appended to document when .replaceChild called ?
Try substituting
renderDiv.appendChild(aHref);
for
renderDiv.replaceChild(aHref, document.getElementById("dllink"));
I have a Python websocket application which sends an image path to a JavaScript HTML file. When the image path is received, I change the background image of the webpage to the supplied image.
The issue I'm having at the moment, is when the background changes from the old image to the new, there is a momentary 'flash' of which, which suggests that there is a period of time (albeit very brief) where the new image is being loaded.
I've tried various preloading methodologies, but I'm very new to JavaScript, so am not sure which method would provide for a seamless transition between the two images. This is the method I currently have implemented:
var NewImage = new Image();
NewImage = message.data; //This is the image string received from Python
document.body.style.backgroundImage = "url('" + NewImage + "')";
The above displays the image as desired (including my CSS formatting), but the transition is unsightly.
I also had a play around with the following method, which makes more sense to me, but I couldn't get it to work.
var NewImage = new Image();
//Websocket function here
PreloadImage;
function PreloadImage() {
NewImage.onload = ImageLoadComplete();
NewImage.src = message.data;
}
function ImageLoadComplete() {
document.body.style.backgroundImage = "url('" + NewImage + "')"
}
I'm not sure how to pass variables between the functions in this second method. Given the explicit 'onload' call in this method, I feel that this may provide the functionality I'm after.
How can I preload the images in order to seamlessly transition between them?
EDIT: The working code is posted below. Thanks to #blender for pointing me in the right direction :)
var NewImage = new Image;
NewImage.src = message.data; //Data from Python
if (NewImage.complete) {
NewImage.onload = ImageLoadComplete();
} else {
NewImage.onload = ImageLoadComplete;
}
function ImageLoadComplete() {
document.body.style.backgroundImage = "url('" + NewImage.src + "')";
}
You're not actually passing a callback function:
NewImage.onload = ImageLoadComplete();
You're passing in the result of calling ImageLoadComplete(), which means you call your callback immediately. Don't call the function and your code should work as expected (most of the time):
NewImage.onload = ImageLoadComplete;
One issue that you'll encounter is that onload may not get called by some browsers if the image is loaded from cache. You have to call the callback manually if that's the case:
if (NewImage.complete || NewImage.height > 0) {
ImageLoadComplete();
} else {
NewImage.onload = ImageLoadComplete;
}
Is it possible to restart a gif animation without downloading the file every time?
My current code looks like this:
var img = new Image();
img.src = 'imgages/src/myImage.gif';
$('#id').css('background-image', 'url("' + img.src + '?x=' + Date.now() + '")' );
Edit
When I insert the gif into the dom it didn't restart the gif animation. I can only achieve this by appending a random string to the image src but this will download the image again.
I want to know if it is possible to restart the gif animation without downloading the gif.
I've had similar requirement.
var img = document.createElement("img"),
imageUrl = "http://i73.photobucket.com/albums/i231/charma13/love240.gif";
img.src = imageUrl;
document.body.appendChild(img);
window.restartAnim = function () {
img.src = "";
img.src = imageUrl;
}
for example on facebook - animated emoticons are not .gifs but a set of static frames on png file with dynamically set background offset. This way you have full control over your animation from javascript - you can even pause/unpause it or change its speed.
It's possible to split your .gif file into separate frames and generate a .png file on server side dynamically.
This looks like a good weekend project for me ;)
restartGif(imgElement){
let element = document.getElementById(imgElement);
if (element) {
var imgSrc = element.src;
element.src = imgSrc;
}
}
// Example:
restartGif("gif_box")
function refreshgif() {
var giffile = $(".gif-class");
giffile.src = giffile.src;
}
I had a similar problem and I solved it by adjusting the image's display attribute before restarting the gif. Also, set the timeout to make sure that the restarting the gif will run after the image attribute is changed.
const img = document.getElementById("gif");
img.style = "display: none;";
img.style = "display: block;";
setTimeout(() => {
img.src = img.src;
}, 0);
This is inspired by this answer.
Just make it loop forever? otherwise you could use an ajax request every (duration of gif) to restart it.
even with javascript it would be possible;
var gif
window.onload=function () {
gif=document.getElementById('id')
setInterval(function () {
gif.src=gif.src.replace(/\?.*/,function () {
return '?'+new Date()
})
},5000)//duration of your gif
}
This may help you,
var img = new Image();
src = 'imgages/src/myImage.gif';
img.src=src;
$('body').append(img);
setInterval(function(){
t=new Date().getTime();
$("img").attr("src", src+'?'+t);
},5000);
create a function in javascript and then reput the image in the same place. when you want to replay the Gif call this function.
function replayGif(){
var img = new Image();
img.src = 'imgages/src/myImage.gif';
$('#id').css('background-image', 'url("' + img.src + '?x=' + Date.now() + '")' );
}
The simplest javascript solution:
Function:
function restartGif(ImageSelector){
var imgSrc=document.querySelector(ImageSelector).src;
document.querySelector(ImageSelector).src=imgSrc;
}
Call function:
restartGif(SELECTOR) // Example: restartGif('.homer')
Example: http://jsfiddle.net/nv3dkscr/
Try to set the src of the gif animation to itself or set it to an empty string followed by the original src again. ;)