I am trying to remove a lag on an image carousel on a personal website I have been working on. I was able to make the carousel work fine, but the images are really laggy until I make my way all the way through the carousel of the photoalbum (you can see what I have here). I have the code set up so that the image file locations are in an array and the src of the background image changes to a new location based on adding new text from the array. Do you have a recommendation on how I can remove the lag? I have tried a few things with the fetch api but I have only used this to fetch and parse json data so I am a bit confused on how to make it work on local files, but I assume I need to somehow make this asynchronous. Any help or resources you can share is greatly appreciated!
The button cycles through like so:
let album = 2;
let currSlide = 0;
divContainer.style.backgroundImage = picArray[album][currSlide];
right.addEventListener('click', () => {
if(currSlide == picArray[album].length - 1){
currSlide = 0;
divContainer.style.backgroundImage = picArray[album][currSlide];
}
else {
currSlide = currSlide + 1;
divContainer.style.backgroundImage = picArray[album][currSlide];
}
});
and the array looks like this:
let picArray = [
[ "url('Pictures/Amsterdam/1.jpg')",
"url('Pictures/Amsterdam/2.jpg')",
"url('Pictures/Amsterdam/3.jpg')",
"url('Pictures/Amsterdam/4.jpg')",
"url('Pictures/Amsterdam/5.jpg')",
"url('Pictures/Amsterdam/6.jpg')",
"url('Pictures/Amsterdam/7.jpg')",
"url('Pictures/Amsterdam/8.jpg')",
"url('Pictures/Amsterdam/9.jpg')"
],
[ "url('Pictures/OregonCoast/1.jpg')",
"url('Pictures/OregonCoast/2.jpg')",
"url('Pictures/OregonCoast/3.jpg')",
"url('Pictures/OregonCoast/4.jpg')"
]
Your images are too long, so it take time to load.
One way to improve. Load image before ur carousel started. Use show hide to toggle.
Pre cache images using the network.
Use a small image for display in thumbnail.
See the sample below.
let album = 2;
let currSlide = 0;
const divContainer = document.getElementById("images");
const right = document.getElementById("rightB");
let picArray = [
"https://nickcosmo.com/Pictures/RoseGarden/1.jpg",
"https://nickcosmo.com/Pictures/RoseGarden/2.jpg",
"https://nickcosmo.com/Pictures/RoseGarden/3.jpg",
"https://nickcosmo.com/Pictures/RoseGarden/4.jpg",
];
divContainer.innerHTML = picArray.map((src) => `<img src="${src}" />`).join("");
const images = divContainer.querySelectorAll("img");
let index = 0;
images[index].classList.add("active");
right.addEventListener("click", () => {
images.forEach((img) => img.classList.remove("active"));
images[index++].classList.add("active");
});
#images img {
display: none;
}
#images .active {
display: block !important;
}
<div class="carousel">
<button class="moveB" id="leftB">‹</button>
<button class="moveB" id="rightB">›</button>
<div id="images">
</div>
</div>
Related
Good day! So I have been practising web development again and found Laravel to be fun to learn (and I'm enjoying it a lot) and I have decided to recreate my portfolio website with it to practice it.
So the problem is this:
I am trying to display a list of images from a folder called designImages and this will be updated every time I have a good UI design. so it makes sense to make it dynamically ready so I do not have to manually add <img> tags for every image and make my process a lot longer. I plan to just make a js file that will only be adjusted once depending on how many images are currently in the folder.
But the problem is when I display the images on my blade page, it shows the broken image icon
view it here
EDIT: When I try to inspect element, the image is not displaying and instead, shows 404 error. mywebsite.test/designImages/design-1 for example.
The code on my js file is this
const imageContainer = document.querySelector(".imageContainer");
for (let i = 1; i < 14; i++) {
const img = document.createElement("img");
img.src = "{{ asset('designImages/design-${i}.png') }}";
imageContainer.append(img);
}
and the code for the master file (app.blade.php) for my index.blade.php is:
<body>
#yield('content-5')
#stack('head')
</body>
and the index.blade.php code is this:
#section('content-5')
<div class="imageContainer">
<!-- images will come here -->
</div>
#endsection
#push('head')
<script src="{{ asset('js/imageGrid.js')}}"></script>
#endpush
Any help or tips will be greatly appreciated :)
-----EDIT-----
Fixed it! :) the updated javascript code is this:
const templateURL = "storage/designImages/design-?.png";
const imageContainer = document.querySelector(".imageContainer");
for (let i = 1; i < 14; i++) {
const img = document.createElement("img");
img.src = templateURL.replace("?", i);
imageContainer.append(img);
}
fixed it using this code:
const templateURL = "storage/designImages/design-?.png";
const imageContainer = document.querySelector(".imageContainer");
for (let i = 1; i < 14; i++) {
const img = document.createElement("img");
img.src = templateURL.replace("?", i);
imageContainer.append(img);
}
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
}
}
I've been given two examples of how to do this but neither is doing both things that I'm looking to do. My website should include:
Rotating Image Banner (3 images), that changes every few seconds
Each image should be clickable and redirect you to a different URL
In our recent lecture, the professor wrote this code on the board and said that this was how you did that. However, it's not working for me.
<html>
<head>
<script language=JAVASCRIPT type=TEXT/JAVASCRIPT>
//I'm not sure when to use '' or ""
//I replaced some of the "picture.jpg" images with links to images. I'm not sure if I used the right syntax.
adImages = new Array("https://i.picsum.photos/id/666/800/200.jpg",
"https://i.picsum.photos/id/420/800/200.jpg",
"https://i.picsum.photos/id/888/800/200.jpg");
adURL = new Array("https://google.com","https://github.com","https://stackoverflow.com");
thisAd = 0;
//length of what?
imgCt = adImages.length;
function rotate()
{
if (document.images)
{
thisAd++;
//Is it better practice to use "==="?
if (thisAd == imgCt)
{
thisAd = 0;
}
document.adBanner.src=adImages[thisAd];
setTimeout("rotate()", 2 * 1000);
}
}
function newLocation()
{
document.location.href = adURL[thisAd];
}
</script>
</head>
//I don't understand what this is at all
<body onload=rotate()>
//Apparently <center> is obsolete?
<center>
<p><font size=4>Rotating Banner <font color=#ff0000>Assignment 6</font> Rotate Party -
Udemy</font>
</p>
<a href="javascript:newLocation()"><IMG height=105 alt="Ad Banner"
src="https://i.picsum.photos/id/666/800/200.jpg" width=610 name=adBanner></a>
</center>
</body>
</html>
Just a heads up. I've been posting my slides from class on Reddit the past couple of weeks and I've received a lot of comments about things being horribly out of date. If you can, please give me examples that are more modern or better practices than what you see me learning. You can find the conversations about my experience learning JavaScript in community college here if you're interested: https://www.reddit.com/user/gettupled/
The second example we were given was a YouTube video that gave the following example. However, it does not include the option of clicking the image and being sent to a URL. I'm not sure if it's common to post HTML, CSS and Javascript code in the body of a message so I'll just attach a codepen unless told otherwise. This code comes from Travesy Media.
https://codepen.io/vitalwheat/pen/QWbEyqN
Thanks everyone. This is my first post here. Hi.
There are many way to implement this. Here is one of the way to do it.
working Demo
(function() {
"use strict";
const imageList = [
"https://i.picsum.photos/id/666/800/200.jpg",
"https://i.picsum.photos/id/420/800/200.jpg",
"https://i.picsum.photos/id/888/800/200.jpg"
];
const urlList = [
"https://google.com",
"https://github.com",
"https://stackoverflow.com"
];
function createRotatingBanner(rotationTime) {
const $adsBanner = document.querySelector(".adBanner");
let $bannerList;
let currentBannerRendered = 0;
function renderBanner() {
Array.from($bannerList).forEach((banner, bannerIndex) => {
banner.className = bannerIndex === currentBannerRendered ? "" : "hide";
});
currentBannerRendered = (currentBannerRendered+1)%$bannerList.length;
}
// creating Banner image and setting them to hide
function createBanner() {
const fragement = new DocumentFragment();
imageList.forEach((image, index) => {
const banner = document.createElement("img");
banner.src = image;
// wrapping image with anchor element
const anchor = document.createElement("a");
anchor.href = urlList[index];
// hide all the banner
anchor.className = "hide"
anchor.appendChild(banner);
fragement.appendChild(anchor);
});
const cloneFragement = [...fragement.children];
$adsBanner.appendChild(fragement);
return cloneFragement;
}
$bannerList = createBanner();
renderBanner();
setInterval(renderBanner, rotationTime);
}
createRotatingBanner(2000);
})();
.hide {
display: none;
}
<div class="adBanner"></div>
I have a div that contains a number of Instagram images, produced by the instafeed.js plugin. After running the plugin, the resultant HTML looks like this:
<div id="instafeed">
<a><img /></a>
<a><img /></a>
<a><img /></a>
etc...
</div>
I am trying to find a way to load the contents of this div into an array; I believe that the easiest way would be to just take the tags, which is fine.
I'm pretty inexperienced with both JS and jQuery, which is why I'm having difficulty achieving this and I've not been able to find any forum posts that quite do what I'm hoping to achieve.
So far, all I'm trying to do is load the contents of the div into an array and print it back out to the document, which should (in my mind anyway) add the tags back into the HTML. I'm trying with both JavaScript and jQuery and having little success with either. I'd appreciate any thoughts:
JS:
var containerDiv = document.getElementById('instafeed');
var pics = containerDiv.getElementsByTagName('img');
console.log(pics); //Tells me at least that I have an array of img
for (var i = 0; i < pics.length; i++) {
document.write(pics[i]);
} //Seemingly does nothing
jQuery:
(I'm really sorry if this code is just all wrong, I really don't know jQuery very well at all)
$(document).ready(function() {
var pics = [];
$('#instafeed').find('img').each(function() {
pics.push($(this));
});
for (i = 0; i < pics.length; i++) {
console.log(pics[i]);
}
});
Any thoughts, tips or pointers would be much appreciated.
Edit:
Just to add a little background to my problem, to avoid causing any more confusion.
I'm trying to pull four random images from a user-specific Instagram feed for display on a website. instafeed.js can pull just four images and it can randomise the images, but Instagram itself always sends the four most recent images, so the plugin is just randomising the order of the same four pictures each time.
I'm trying to let the plugin send through every picture, which will go into the div instafeed. From here I want to load all of the contained images into an array so that I can randomly pick four images for display on the site.
JQuery code that you write is correct. Only you need the div where you need to put the images.
$(document).ready(function() {
var pics = [];
$('#instafeed').find('img').each(function() {
pics.push($(this));
});
for (i = 0; i < pics.length; i++) {
$('div#yourDiv').append(pics[i]);
}
});
See the line of the for()
You can extract only the SRC of the images and then make like you want
$('#instafeed').find('img').each(function() {
pics.push($(this).attr('src'));
});
console.log(pics); // returns an array of src.
Thank you to everyone who has tried to help me along with this. It turns out that the problem I was having stemmed from my query attempting to run before instafeed.js had been able to pull the images through from Instagram, and so there was nothing for it to find in the div. I've managed to fix this with a setTimeout.
For anyone who is interested, and just in case anyone else might come across this in future with a similar problem, here is my complete code (it's a little inelegant I'm sure, but I'm still a relative novice at JS.)
function snagImages() {
var pics = [];
$('div#instafeed').find('img').each(function() {
pics.push($(this).attr('src'));
});
reduceGallery(4, pics);
}
function reduceGallery(limit, pics) {
if (limit === undefined) {
limit = 4;
}
var gallery = [];
while (gallery.length < limit) {
var j = Math.floor(Math.random() * pics.length);
if ( gallery.indexOf(pics[j]) > -1) {
continue;
}
gallery.push(pics[j]);
}
displayPics(gallery);
}
function displayPics(gallery) {
for (var i = 0; i < gallery.length; i++) {
document.getElementById('gallery').innerHTML += '' + '<img src="' + gallery[i] + '" alt="Gallery Image" />' + '';
}
}
var userFeed = new Instafeed( {
options
});
userFeed.run();
setTimeout(function() { snagImages() }, 500);
I am trying to build a simple 3 grid gallery, the images inside it are all with different heights and I was after a tiled gallery... So I have made one that works with a bit of JavaScript.
However, when I tried to add another gallery in the same page, something weird happened, live preview here: http://loai.directory/test/gallery
The HTML, CSS and JS can be found fully placed in this jsfiddle: http://jsfiddle.net/aY5Gu
As you can see in the live preview, all the gridElemetns in grid3 are appending to grid3 in all the threeGrid galleries! After trying to debug, I have concluded that the problem is from the JS:
//Three Grids System
var gridElement = $(".gridElement", ".grid3");
GalleryGrid(); $(window).resize(GalleryGrid);
function GalleryGrid() {
var grid3 = $('.threeGrids .grid3');
var width = $(window).width();
if (width < 1024 && width > 770) {
var grid1 = $('.threeGrids .grid1');
var grid2 = $('.threeGrids .grid2');
for (var i = 0; i < gridElement.length; i++) {
if (i < gridElement.length / 2) {
grid1.append(gridElement[i]);
} else {
grid2.append(gridElement[i]);
}
}
} else {
grid3.append(gridElement);
}
}
What is going wrong? I can't seem to be able to go figure out what is wrong from there.
That's because .threeGrids and .grid1... appear more than one time on your page. Therefore jquery automatically appends things to all of them.
Try selecting by something like:
$('.wrapper').each(
function(){
var grids = $(this).find('.threeGrids');
(...do manipulation with grids...)
}
);
This way you enter each .wrapper separately and deal with only elements that are inside it.