Random image load - javascript

so I already have a image randomiser, but i am now looking to extend this so that IF image 1 was loaded last, load image 2 and so on.
$(document).ready(function () {
var images = ['imageTest.jpg', 'imageTest2.jpg', 'imageTest3.jpg', 'imageTest4.jpg'];
$('.mainHero-fluid').css({
'background-image': 'url(/assets/images/' + images[Math.floor(Math.random() * images.length)] + ')',
});
});
how can I do this?

I guess somthing like that should do it. You can gain the current Image from the source attribute of the imageā€¦
//copy the whole list
var newImages = [].concat(images), newImage;
//remove the current image
newImages.splice(images.indexOf(<currentImage>),1);
//get a random entry
newImage = newImages[Math.round(Math.random() * (newImages.length - 1))];
Good luck!

Related

Javascript: preload next image

not very big on JS.
I currently have a script I use to load/change background images every xxx seconds.
What I would like is to display an image and preload the next one so it displays seamlessly (ie: no jittering or slow loads).
Here is my current script, can this be adapted to achieve such a result?
<!-- Background Image Changer inpired by: https://stackoverflow.com/a/7265145 -->
var images = ['images/image01.jpg',
'images/image02.jpg',
'images/image03.jpg',
'images/image04.jpg',
'images/image05.jpg',
'images/image06.jpg',
'images/image07.jpg',
'images/image08.jpg',
'images/image09.jpg',
'images/image10.jpg',
'images/image11.jpg',
'images/image12.jpg',
'images/image13.jpg',
'images/image14.jpg',
'images/image15.jpg',
'images/image16.jpg',];
var numSeconds = 30;
var curImage = 0;
function switchImage()
{
curImage = (curImage + 1) % images.length
document.body.style.backgroundImage = 'url(' + images[curImage] + ')'
}
window.setInterval(switchImage, numSeconds * 1000);
NOTES: There are 50 images in my script. I've only used fake named placeholders for clarity.
EDIT: To be clear, I only want one image displayed and the next (one) image to be preloaded. It's running on a RPi 3b so not much memory is available.
I want to add a different answer here. There are a few options you can use to improve your web page performance. Using <link> with preconnect and preload rel value can helps you to load resources before using them:
Use preconnect keyword for the rel attribute to tell the browsers that the user is likely to need resources from this origin and therefore it can improve the user experience by preemptively initiating a connection to that origin.
<link rel="preconnect" href="<your-images-base-url">
Use preload keyword for the rel attribute to declare fetch requests in the HTML's , specifying resources that your page will need very soon. This ensures they are available earlier and are less likely to block the page's render, improving performance. Taken from https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload
Create preload link:
const preloadLink = document.createElement('link');
document.head.appendChild(preloadLink);
preloadLink.rel = 'preload';
preloadLink.as = 'image';
function preloadNextImage(href) {
preloadLink.href = href;
}
function switchImage()
{
curImage = (curImage + 1) % images.length
document.body.style.backgroundImage = 'url(' + images[curImage] + ')';
preloadNextImage(/* <next-image-url> */)
}
You could just load the next image when displaying the current one using the JavaScript Image object. When switchImages runs again then the image will be already in the browsers cache. Also, the cached images are stored in a new array, so the cache "generator" will be ran only once. With this snippet you will need enough delay between iterations, so the next image will have enough time to be downloaded from the sever.
var images = ['images/image01.jpg',
'images/image02.jpg',
'images/image03.jpg',
'images/image04.jpg',
'images/image05.jpg',
'images/image06.jpg',
'images/image07.jpg',
'images/image08.jpg',
'images/image09.jpg',
'images/image10.jpg',
'images/image11.jpg',
'images/image12.jpg',
'images/image13.jpg',
'images/image14.jpg',
'images/image15.jpg',
'images/image16.jpg',];
var numSeconds = 2;
var curImage = 0;
var cache = [];
function switchImage()
{
curImage = (curImage + 1) % images.length;
document.body.style.backgroundImage = 'url(' + images[curImage] + ')';
if(images[curImage + 1] && !cache[curImage + 1]) {
cache[curImage + 1] = new Image();
cache[curImage + 1].src = images[curImage + 1];
}
}
window.setInterval(switchImage, numSeconds * 1000);

COMBINING CSS and SVG Filters to Edit and Save an Image [duplicate]

I need to save an image after using CSS filters on the client-side (without using a backend). What I have so far:
Use CSS filters
Convert to canvas
Save with var data = myCanvas.toDataURL("image/png");
Crying. Image was saved without effects.
Index.html
<div class="large-7 left">
<img id="image1" src="./img/lusy-portret-ochki-makiyazh.jpg"/><br>
<canvas id="myCanvas"></canvas>
</div>
Photo.js
var buttonSave = function() {
var myCanvas = document.getElementById("myCanvas");
var img = document.getElementById('image1');
var ctx = myCanvas.getContext ? myCanvas.getContext('2d') : null;
ctx.drawImage(img, 0, 0, myCanvas.width, myCanvas.height);
var grayValue = localStorage.getItem('grayValue');
var blurValue = localStorage.getItem('blurValue');
var brightnessValue = localStorage.getItem('brightnessValue');
var saturateValue = localStorage.getItem('saturateValue');
var contrastValue = localStorage.getItem('contrastValue');
var sepiaValue = localStorage.getItem('sepiaValue');
filterVal = "grayscale("+ grayValue +"%)" + " " + "blur("+ blurValue +"px)" + " " + "brightness("+brightnessValue+"%)" + " " + "saturate(" + saturateValue +"%)" + " " + "contrast(" + contrastValue + "%)" + " " + "sepia(" + sepiaValue + "%)" ;
$('#myCanvas')
.css('filter',filterVal)
.css('webkitFilter',filterVal)
.css('mozFilter',filterVal)
.css('oFilter',filterVal)
.css('msFilter',filterVal);
var data = myCanvas.toDataURL("image/png");
localStorage.setItem("elephant", data);
if (!window.open(data)) {
document.location.href = data;
}
}
However, this produces an image without any filters.
There is a little known property on the context object, conveniently named filter.
This can take a CSS filter as argument and apply it to the bitmap. However, this is not part of the official standard and it only works in Firefox so there is the limitation.. This has since this answer was originally written become a part of the official standard.
You can check for the existence of this property and use CSS filters if it does, or use a fallback to manually apply the filters to the image if not. The only advantage is really performance when available.
CSS and DOM is a separate world from the bitmaps that are used for images and canvas. The bitmaps themselves are not affected by CSS, only the elements which acts as a looking-glass to the bitmap. The only way is to work with at pixel levels (when context's filter property is not available).
How to calculate the various filters can be found in the Filter Effects Module Level 1. Also see SVG Filters and Color Matrix.
Example
This will apply a filter on the context it self. If the filter property does not exist a fallback must be supplied (not shown here). It then extracts the image with applied filter as an image (version to the right). The filter must be set before next draw operation.
var img = new Image();
img.crossOrigin = "";
img.onload = draw; img.src = "//i.imgur.com/WblO1jx.jpg";
function draw() {
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d");
canvas.width = this.width;
canvas.height = this.height;
// filter
if (typeof ctx.filter !== "undefined") {
ctx.filter = "sepia(0.8)";
ctx.drawImage(this, 0, 0);
}
else {
ctx.drawImage(this, 0, 0);
// TODO: manually apply filter here.
}
document.querySelector("img").src = canvas.toDataURL();
}
canvas, img {width:300px;height:auto}
<canvas></canvas><img>
CSS filters applied to the canvas will not be applied to the image that is produced. You either need to replicate the filters in canvas or rather re apply the same filters to the generated image.
Try putting the generated image data into the source of an img tag & apply the same filters.
Your CSS properties are not actually applied to the canvas data. Think of the CSS as being another layer placed over the canvas element. You can implement your own image filters by using context.getImageData to get an array of raw RGBA values, then do your filter work and then write it back with context.putImageData. However, I think you really just want to save the output of the CSS filters. You may be able to do this using a tool like rasterizeHTML
Note, if src of img is not located at same origin calling var data = myCanvas.toDataURL("image/png") , may cause error
Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': tainted canvases may not be exported.
Note also that image at html at Question appear to be type jpg , not png
<img id="image1" src="./img/lusy-portret-ochki-makiyazh.jpg"/>
A possible "workaround" could be to set img src as a data URI of image ; calling
var data = myCanvas.toDataURL("image/jpg")
Though as noted , at Answers above , would not appear to preserve css filter set at img element.
Note, "workaround" ; "save image" here , would be "save html" ; as the "download" would be an objectURL of the DOM html img element.
Note also , img src within saved html file will still be original local or external src of image ; if not converted to data URI before loading.
Approach is to set window.location.href as an objectURL reference to DOM img element outerHTML , which should preserve style attribute set at .css("[vendorPrefix]-filter", filterVal)
Try utilizing URL.createObjectURL , URL.revokeObjectURL ; setting css filter at img , instead of canvas element ; creating Blob of img outerHTML , type:text/html ; create reference to URL.createObjectURL: objURL ; set window.location.href to objURL ;
call URL.revokeObjectURL on objectURL reference objURL
var buttonSave = function() {
var img = document.getElementById("image1");
// filters
var grayValue = "0.2";
var blurValue = "1px";
var brightnessValue = "150%";
var saturateValue = "0.2";
var contrastValue = "0.2";
var sepiaValue = "0.2";
// `filterVal`
var filterVal = "grayscale(" + grayValue + ") "
+ "blur(" + blurValue + ") "
+ "brightness(" + brightnessValue + ") "
+ "saturate(" + saturateValue + ") "
+ "contrast(" + contrastValue + ") "
+ "sepia(" + sepiaValue + ")";
// set `img` `filter` to `filterVal`
$(img)
.css({
"webkit-filter": filterVal,
"moz-filter": filterVal,
"ms-filter": filterVal,
"o-filter": filterVal
});
// create `blob` of `img` `outerHTML` ,
// `type`:`text/html`
var blob = new Blob([img.outerHTML], {
"type": "text/html"
});
// create `objectURL` of `blob`
var objURL = window.URL.createObjectURL(blob);
console.log(objURL);
// download `filtered` `img` as `html`
var download = $("<a />", {
"download": "image-" + $.now(),
"href": objURL,
// notify file is type `html` , not image
"title":"click to download image as `html` file"
}).appendTo("body");
$(img).appendTo("a");
$("a").on("click", function() {
// set `location.href` to `objURL`
window.location.href = objURL;
$(window).one("focus", function() {
// revoke `objURL` when `window` regains `focus`
// after "Save as" dialog
window.URL.revokeObjectURL(objURL);
});
});
}
window.onload = buttonSave;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div class="large-7 left">
<img id="image1" src="http://lorempixel.com/200/200/cats" />
</div>

Javascript Slide show

I have a simple fading slide-show which works great for a while, but runs to about 300 images. After a while it starts jumping and missing some, which I assume is down to too many images being loaded. Is there a way of 'unloading' images once viewed, or is it likely to be something else?
Let all images load before you display the slide show, or skip not loaded images.
You could do this like this for example:
var images = ['./path1.jpg', './path2.jpg']; // Array with all images
var imageCount, imagesLoaded, c;
imageCount = images.length; // Get images count
imagesLoaded = 0;
for (c = 0; c < imageCount ; c++){ // Loop thorough all images
var image = document.createElement('img'); // Create img tag
image.setAttribute('src', images[c]); // Set src attribute
document.body.appendChild(image); // Add img tag to body
image.onload = function() {
imagesLoaded++; // Add loaded image to loaded images count
console.log('Loaded: ' + imagesLoaded + '/' + imageCount); // debug
if (imagesLoaded == imageCount){ // when all images loaded
// Start your slideshow
}
}
}

JS: access image height after pulling it from an array

I've populated an array of images as seen here
$($target + " img").each(function() {
images.push(this);
});
I then want to access the first image in this array, specifically it's height
this.begin = function() {
var first = images[0];
};
However, when I try to access first.height and/or first.clientHeight, it's 0.
When I console.log(first); I get: <img src="img/1.jpg" class="sluider-img">.
When I console.log(images) I get: [img.sluider-img, img.sluider-img, img.sluider-img, img.sluider-img].
I can see that the target has a height / clientHeight by looking through the array seen in the above line.
Any reason I can't access the height of this element when I fetch it from the array, however I can see it while it's in the array?
I'm trying to access the height as follows
this.begin = function() {
var first = images[0];
console.log(first.clientHeight);
};
If so, how? Cheers guys.
EDIT:
When I console.log images array:
... className: "sluider-img"clientHeight: 647clientLeft: 0clientTop: 0clientWidth: 1478
... // repeat for each image element
When I console.log images[0]:
<img src="img/1.jpg" class="sluider-img">
When I do the following:
images.forEach(function(image) {
console.log(image);
});
>>
<img src="img/1.jpg" class="sluider-img">
<img src="img/2.jpg" class="sluider-img">
<img src="img/3.jpg" class="sluider-img">
<img src="img/4.jpg" class="sluider-img">
When I do the following:
images.forEach(function(image) {
console.log(image);
});
console.log(images); // this is new?
>>
sluider.js:37 img.sluider-img
sluider.js:37 img.sluider-img
sluider.js:37 img.sluider-img
sluider.js:37 img.sluider-img (it gets the image classes)
My full code
images = [];
prepare_image = function(image) {
var img = document.createElement("img");
img.setAttribute("src", image);
img.setAttribute("class", "sluider-img");
element.appendChild(img);
};
this.initialize = function(settings) {
/* creates the images and adds them into the
sluider container */
settings.images.forEach(function(image) {
this.prepare_image(image);
});
$(".sluider-img").each(function() {
images.push(this);
});
};
this.begin = function() {
/* at this point I need to get the height
of the tallest image so I can base the
container off of that. */
console.log(images);
};
And
var sluider = $($target).sluider().data($plugin);
sluider.initialize(
{
title: "TITLE",
target: $target,
images: [
"img/1.jpg",
"img/2.jpg",
"img/3.jpg",
"img/4.jpg"
]
}
);
sluider.begin();
How about checking if image was loaded?
var first = images[0];
if(first.complete){
console.log(first.height);
}else{
first.onload=function(){console.log(first.height);}
}
I do not know the EXACT scenario, but here is my answer based on understanding.
var images = [];
$.each($('.sluider-img'), function(i,d){
images.push(d);
});
var first = images[0];
var height = first.clientHeight;
alert(height);
See it working here
Basically, what you are doing is right, it is just that maybe you are not getting the value itself because of the way you are accessing the array and the value that you need (maybe because of the function that you created or you are not calling function begin)
I tried to do the same and i obtain some interesting results:
var images = [];
$('.sluider-img img').each(function(){
images.push(this)
});
console.log(images[0]);
console.log(images[0].clientHeight + " " + $(images[0]).height());
By executing the same code 20 times on Chrome I obtain, on the same image, sometimes:
0 0 (wrong)
others:
220 220 (correct heights)
Images are loaded and the code results are correct or wrong in random order.
Unfortunately I can't explain the source of this problem, but probably is the source of your frustration..
(sorry, I meant to comment but I can't because of low reputation)

Image preloading with array

I am using the following code to preload images in an image gallery:
$(window).bind('load', function(){
var imageNumber = $(".image").attr("alt");
var imageUp = parseInt(imageNumber) + 1
var imageUp2 = parseInt(imageNumber) + 2
var imageDown = parseInt(imageNumber) - 1
var preload = [
'image' + imageUp + '.jpg',
'image' + imageUp2 + '.jpg',
'image' + imageDown + '.jpg',
];
$(document.createElement('img')).bind('load', function(){
if(preload[0]) this.src = preload.shift();
}).trigger('load');
});
I modified another basic javascript/jQuery preload script, adding variables in order to get a numeric value from the current image's alt-tag and preload images that are immediately before and after it (n+1 n+2 n-1) in the gallery. This works, though I imagine it may be kind of ugly.
What I want to do is add or call another array containing all images in the directory, so that after the previous and next images have loaded, the current page continues to preload other images, saving them in the browsers catche for future viewing as the user moves through the gallery.
Ideally, this second array would be called from an external .js file, so as to prevent having to update every page individually. (Or maybe it would be easier to save the entire script in a external .js file for each directory and fill out the rest of the array based on that directory's contents?).
Web design is only a hobby for me (I'm a photographer), so my knowledge of javascript is limited--just enough to customize pre-built functions and collage scraps of code.
I would really appreciate if someone could point me in the right direction on how to modify my code.
Thanks in advance,
Thom
I have never used a jQuery preload script but i have done a lot of preloading with 'vanilla' javascript.
Try the code i have added below, it may solve your problem.
function preLoad() { // my preload function;
var imgs = arguments, imageFolder = [];
for (var i = 0; i < imgs.length; i += 1) {
imageFolder[i] = new Image();
imageFolder[i].src = imgs[i];
}
}
var gallary = []; // all gallary images
$(window).bind('load', function(){
var imageNumber = $(".image").attr("alt");
var imageUp = parseInt(imageNumber) + 1
var imageUp2 = parseInt(imageNumber) + 2
var imageDown = parseInt(imageNumber) - 1
var preload = [
'image' + imageUp + '.jpg',
'image' + imageUp2 + '.jpg',
'image' + imageDown + '.jpg',
];
$(document.createElement('img')).bind('load', function(){
if(preload[0]) this.src = preload.shift();
}).trigger('load');
preLoad(gallary); // preload the whole gallary
});
EDIT
preLoad() : this function accepts image urls as arguments e.g preLoad('image_one.jpg', 'image_two.jpg','image_thre.jpg');
The preLoad function has two variables var imgs and var imageFolder, imgs stores all the image urls and imageFolder stores image Objects, that is, preload loaded images.

Categories

Resources