Prerender images from URL in reactjs - javascript

Is it possible to prerender a list of images based on URL to prevent first loading on display with react or JS?
Thanks in advance.
EDIT: I have a carousel of images and all images are display one by one. When an image are are display for the first time this image take some time to be render because she need to be get from the url. And if I display this same image a second time I will not wait. Then I want to know if there is a solution to preload all images directly after get the url in a ComponentDidMount even the loading become longer.
An other example: I have a list of image and I want display them all at the same time. How can I preload them all before end the loading and start the render.

Do you simply want to preload images in advance?
The article of the Preloading Content might help.
componentDidMount() {
const imageUrlList = ['a.jpg', 'b.jpg', 'c.jpg'];
this.preloadImages(imageUrlList);
}
preloadImages(urlList) {
let fragment = document.createDocumentFragment();
for (let i = 0; i < urlList.length; i++) {
const imgUrl = urlList[i];
const linkEl = document.createElement('link');
linkEl.setAttribute('rel', 'preload');
linkEl.setAttribute('href', imgUrl);
linkEl.setAttribute('as', 'image');
fragment.appendChild(linkEl);
}
document.head.appendChild(fragment);
}

Not so clear from what you mean by prerender.
By preloading, do you mean that you want that the component renders only when the image is ready?
If so, you could do something like this:
componentDidMount() {
const img = new Image();
img.src = Newman; // by setting an src, you trigger browser download
img.onload = () => {
// when it finishes loading, update the component state
this.setState({ imageIsReady: true });
}
}
render() {
const { imageIsReady } = this.state;
if (!imageIsReady) {
return <div>Loading image...</div>; // or just return null if you want nothing to be rendered.
} else {
return <img src={Newman} /> // along with your error message here
}
}

Related

.appendChild and window.print();

I have the following code:
const printString = // a long string w/ several base64 encoded images;
const printContainer = document.createElement('div');
printContainer.innerHTML = printString;
document.body.appendChild(printContainer);
window.print();
printString is a long string with several largeish base64 encoded images included. The string gets set as the innerHTML of the printContainer and then the whole thing gets printed.
This works okay, but on the initial load of the page, it apparently takes the browser a moment to render the base64 encoded images and in that time, window.print() goes ahead and fires, before all the images have actually loaded into the DOM.
That is, window.print() can fire before .innerHTML has finished rendering the new element.
If I add a brief delay to the window.print(), then everything works fine. Like so:
const printString = // a long string w/ several base64 encoded images;
const printContainer = document.createElement('div');
printContainer.innerHTML = printString;
document.body.appendChild(printContainer);
setTimeout(() => {
window.print();
}, 100);
This isn't a great solution, however, and I would really like to find a solution along the lines of "you just wait until .innerHTML() is actually finished, window.print();
All of this is tested in Chrome, so far.
Any ideas appreciated!
Edit: an answer
This is a modest reworking of #Keith's answer below.
const imgs = document.querySelectorAll('img.images-in-question');
function checkDone() {
if (ready === imgs.length) {
// do stuffs
}
}
function incrementReady(){
ready++;
checkDone();
}
for (const img of imgs) {
if (img.complete) ready++;
else {
img.addEventListener('load', incrementReady);
}
}
checkDone();
Below is a simple script to wait for all images to load.
It basically does a querySelectAll to get all the images, and then attaches the onload event, when the amount of images loaded is equal to the amount of images in the list, everything is then loaded.
This then will of course work with both external URL, and data uri's..
Update, noticed a slight issue with my original image load check, in Chrome sometimes the onload is not fired, I assume it's because if it can pull the resources from cache, it might get loaded before the onload event is even attached, as such I've added a check for the complete flag first. This seems to fix the issue..
const imgs = document.querySelectorAll("img");
let waiting = 0;
let count = 0;
function checkDone() {
if (count === waiting) {
console.log("all images loaded");
}
}
for (const img of imgs) {
if (!img.complete) waiting ++;
else img.addEventListener('load', () => {
count ++;
checkDone();
});
}
checkDone();
<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" style="width:100px;height:100px">
<img src="https://via.placeholder.com/350x150.svg">
<img src="https://via.placeholder.com/300x100.svg">
<img src="https://via.placeholder.com/200x400.svg">
This would be a good case to use requestAnimationFrame.
const printString = // a long string w/ several base64 encoded images;
const printContainer = document.createElement('div');
printContainer.innerHTML = printString;
document.body.appendChild(printContainer);
requestAnimationFrame(function () {
window.print();
});
requestAnimationFrame waits for the next paint and then runs the function, thus you can be sure that window.print() won't run until just after the HTML has been rendered.

Display a Loading icon while images loads

I want to show a background image/loading spinner inside a div that will load an image inside of it, the image will show once it's fully loaded doing something like this:
<div style="background-image:url('imageThatWillAppearBeforeLoad')"></div>
Demo (In jQuery)
How can I have the same using Angular2/Ionic2?
Create a component that shows the placeholder image until the requested image is loaded, and hides the requested image. Once the image is loaded, you hide the placeholder and show the image.
#Component({
selector: 'image-loader',
template: `<img *ngIf="!loaded" src="url-to-your-placeholder"/>
<img [hidden]="!loaded" (load)="loaded = true" [src]="src"/>`
})
export class ImageLoader {
#Input() src;
}
See it working in Plunker.
Update
Now that I understand the requirements better, here's a solution with background image. It's a little hacky, and I like the original one better...
#Directive({
selector: '[imageLoader]'
})
export class ImageLoader {
#Input() imageLoader;
constructor(private el:ElementRef) {
this.el = el.nativeElement;
this.el.style.backgroundImage = "url(http://smallenvelop.com/demo/image-loading/spinner.gif)";
}
ngOnInit() {
let image = new Image();
image.addEventListener('load', () => {
this.el.style.backgroundImage = `url(${this.imageLoader})`;
});
image.src = this.imageLoader;
}
}
Updated plunker.
Here is a copy of one of my posts
I finally solved that problem with CSS! When an image is loading in ionic 2, the ion-img tag doesn't have any class. However, when the image is finally loaded, the ion-img tag get the class "img-loaded".
Here is my solution :
<ion-img [src]="img.src"></ion-img>
<ion-spinner></ion-spinner>
And my CSS :
.img-loaded + ion-spinner {
display:none;
}
Simply use this function
loadImage(element: HTMLElement, imagePath: string, spinnerPath: string) {
element.tagName === 'img'
? element.setAttribute('src', spinnerPath)
: (element.style.background = `url(${spinnerPath}) 50% 50% no-repeat`);
const image = new Image();
image.crossOrigin = 'Anonymous';
image.src = imagePath;
image.onload = () => {
element.tagName === 'img'
? element.setAttribute('src', imagePath)
: (element.style.background = `url(${imagePath})`);
};
}
You don't have to worry about your element is image or div or whatever it is?
example if you didn't figure out how to use it
ngOnInit() {
const myElement = document.getElementsByClassName('my-element')[0];
// or however you want to select it.
const imagePath = 'path/to/image.png';
const spinnerPath = 'path/to/spinner.gif'; // or base64 spinner url.
this.loadImage(myElement, imagePath, spinnerPath);
}
Happy coding 😉

Detect if Image Exists with File.Exists

i try want to detect if an image exists but can't get it to work. If need to load the image if it exits and if not exits it needs to load a default image. The IF/ELSE is working just the first part does not, what am i doing wrong i get all the time the default image
#{ String imageURL = "http://www.XXXX.com/cdcover.jpg')";
}
#if (File.Exists(imageURL)) {
#section cdcover{ src="http://www.XXXX.com/cd/XX/cdcover.jpg")" }
}
else {
#section cdcover{ src="http://www.XXXX.com/cd/defaulcover.jpg" }
}
Here is a concept:
var bitmapImage = new BitmapImage(); // An image var
bitmapImage.BeginInit();
bitmapImage.UriSource = new Uri("/*image url*/");; // set a value to our var
bitmapImage.EndInit(); img.Source = bitmapImage;
if (File.Exists(bitmapImage)){ // checks if the var has an existing image
//code
}

Dynamically change image in javascript

JavaScript Noob here.
I want to show the dynamically changing image effect like this:
http://dotsignals.org/google_popup.php?cid=202
(if this webpage cannot show changing image, click on any camera at http://dotsignals.org)
I have examined the code, and have some questions:
1.The website uses setImage and refreshSetImage to initialize and refresh the image for a dynamically changing effect. What is the use of Math.random in here? I understand it is a way to differentiate images from different time at the same cam. But how does it works? How would the backend respond?
2.Related to the first question. What is the mechanism of the refreshSetImage? I didn't see any sign of requesting data from the server. Does it send a "GET"? How does it refresh the image?
function setImage(imageID){
var currentImage = imageID;
document.getElementById(currentImage).src ='http://207.251.86.238/cctv9.jpg'+'?math=';
refreshSetImage();
}
function refreshSetImage() {
document.images["myCam"].src = 'http://207.251.86.238/cctv9.jpg'+'?math='+Math.random();
setTimeout('refreshSetImage()',1000);
}
function ScaleSize(imageID) {
var elem = document.getElementById(imageID);
elem.style.width = 500;
elem.style.height = 300;
}
3.How is the backend designed?
4.Now I want to use these two functions in my own project. I want to add a parameter of camID in the setImage and refreshSetImage functions, so the src of the image will change to something like: 'http://..../'+camID+'.jpg'+'?math'. camID is a String that identifies different cameras. I changed it to:
function refreshSetImage(camID) {
document.images["myCam"].src = 'http://207.251.86.238/'+camID+'.jpg'+'?math='+Math.random();
setTimeout('refreshSetImage(camID)',1000);
}
function setImage(imageID,camID){
var currentImage = imageID;
document.getElementById(currentImage).src = 'http://207.251.86.238/'+camID+'.jpg'+'?math=';
refreshSetImage(camID);
}
and got an error :Uncaught ReferenceError: camID is not defined VM132:1. The image is not changing as well. I don't know what is the problem. What is VM132:1 ?
Thanks
check
function refreshSetImage(imageID,camID) {
currentImage = imageID;
url = 'http://207.251.86.238/'+camID+'.jpg'+'?math='+Math.random();
//document.getElementById(currentImage).src= url;
console.log(url);
}
$(document).ready(function(){
imageID = "imageID";
camID = "camID";
setInterval(function() {
refreshSetImage("imageID","camID");
}, 3000);
});
https://jsfiddle.net/Cuchu/vr1ftwg1/

javascript: multiple stop image toggle

I am trying to make an image button on my website toggle wallpaper change frequency options (off,5,10,15,30,30,90 minutes). I have created a custom image for each step (so the user can be aware of the current setting). When implemented the user should be able to repeatedly hit the button to toggle through all 7 options, ultimately looping back to the beginning.
I have some code to swap between two images (below), and have used it for other options on the site (wallpaper on/off), but I just can't figure out a way to get the code to work for my new needs.
if (imageId == 'image1') {
if (document.getElementById) {
var img = document.getElementById(imageId);
img.src = (img.src.indexOf("40_unlocked.jpg") != -1) ? "40_locked.jpg" : "40_unlocked.jpg";
}
}
I expect I will need to determine the current image, then use a switch to advance to the next option, something like the below, but I don't know how to determine the current image - hoping someone can offer a suggestion - thanks in advance!
function changeIt(img) {
var src;
switch (img.id) {
case "example":
src = "n.gif";
break;
case "example2":
src = "n2.gif";
break;
case "example3":
src = "n3.gif";
break;
}
img.src = (img.src.indexOf("jj.gif") < 0 ? "jj.gif" : src);
}
This should get you started
Name your images n0.gif through n6.gif.
toggle.onclick=function(){
//isolate the number of the current image
var num=this.src.split('.gif')[0].split('n')[1]-0;
//add 1 and take mod 7 to loop it back to 0 if it needed
num=++num%7;
//set the src to the new image
this.src='n'+num+'.gif';
}
Try creating an array of all of the src urls & then toggle it like this.
function changeIt(img)
{
var src=img.src;
images=['src1','src2','src3','src4','src5','src6','src7'];
index=images.indexOf(a);
if (index+1>6)
{
index=0;
}
else
{
index+=1;
}
img.setAttribute('src',images[index]);
}

Categories

Resources