Rotating image if width < height with Javascript without modifying each image? - javascript

I'm trying to get all image elements on a html page then check each image if the width < height (portrait) then rotate it.
The problem is my script doesn't work for each image but for all of them because i get the images by "img" tag, then i have no idea how to apply the rotation for individual images.
Is it possible to do this without having to modify the markup for each images (I want to avoid putting ids for every image)?
<script>
$(document).ready(function() {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
img = document.getElementsByTagName("img")[i];
var width = img.clientWidth;
var height = img.clientHeight;
if(width<height){
img.setAttribute('style','transform:rotate(90deg)'); //how do I apply this for each image?
}
else{
}
}
});
</script>

Your code seems to be working for images of the correct dimensions. However, you can change your code a little. For the code that you've given you don't need to do:
img = document.getElementsByTagName("img")[i];
in your for loop at each iteration, as this is an expensive function to run. Instead, you already have the result of document.getElementsByTagName("img"); stored in imgs, so you can use that instead:
img = imgs[i];
See working example below:
$(document).ready(function() {
var imgs = document.getElementsByTagName("img");
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
img = imgs[i];
var width = img.clientWidth;
var height = img.clientHeight;
if (width < height) {
img.setAttribute('style', 'transform:rotate(90deg)');
}
};
});
img {
height: 150px;
width: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Width > Height</p>
<img src="https://media.wired.com/photos/5926db217034dc5f91becd6b/master/w_1904,c_limit/so-logo-s.jpg" />
<p>Width < Height</p>
<img src="https://d1qb2nb5cznatu.cloudfront.net/startups/i/32728-274244db60c65e1cc32abb4c54a2c582-medium_jpg.jpg?buster=1442602512" />
<p>Width < Height</p>
<img src="https://images.unsplash.com/photo-1522092787785-60123fde65c4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=94d6ebf03fdc6a3c8159ac9aeceb0483&w=1000&q=80" />
Also, since your using jQuery, this can be done even easier using jQuery methods:
$(document).ready(function() {
$('img').each((_, elem) => {
let width = $(elem).width();
let height = $(elem).height();
if(width < height) {
$(elem).css({'transform': 'rotate(90deg)'});
}
});
});
img {
height: 150px;
width: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Width > Height</p>
<img src="https://media.wired.com/photos/5926db217034dc5f91becd6b/master/w_1904,c_limit/so-logo-s.jpg" />
<p>Width < Height</p>
<img src="https://d1qb2nb5cznatu.cloudfront.net/startups/i/32728-274244db60c65e1cc32abb4c54a2c582-medium_jpg.jpg?buster=1442602512" />
<p>Width < Height</p>
<img src="https://images.unsplash.com/photo-1522092787785-60123fde65c4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=94d6ebf03fdc6a3c8159ac9aeceb0483&w=1000&q=80" />

I tried the code provided and on many occasion (reload for instance) it doesn't get the width and height of the image.
It seems that instead of using
$(document).ready(fn)
you should use
$(window).on("load", fn)
There was a question on this topic Official way to ask jQuery wait for all images to load before executing something

<script>
$(document).ready(function() {
var imgs = document.getElementsByTagName("img");
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
var img = document.getElementsByTagName("img");//add all images in array
var width = img[i].clientWidth;
var height = img[i].clientHeight;
if(width<height){
img[i].setAttribute('style','transform:rotate(90deg)'); //change style for current image
}
else{
}
}
});
</script>

Related

if img < 500 apply css

i have this code:
var jq111 = jQuery.noConflict();
jq111('.slides img').each(function(){
jq111self = jq111(this).height();
if(jq111self < 500){
jq111(this).addClass( "product-rescue" );
}
});
if an image is less than 500 px apply a CSS class.
But there is a problem, is not working properly, and is applied 1/3 to images larger than 500px.
why?
https://jsfiddle.net/cuaqaxy8/3/
you need to wait for the image to load:
var jq111 = jQuery.noConflict();
jq111('.slides img').on("load", function() {
var jq111self = jq111(this);
if(jq111self.height() < 500){
jq111self.addClass("product-rescue");
}
});

Javascript slideshow shows no image for one iteration

The slideshow shows pic1.jpg through pic8.jpg and then no image for 4 seconds and then starts back at pic1.jpg. I want it to go right back to pic1.jpg after pic8.jpg.
Here is my script:
<script>
var pics = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg", "pic5.jpg", "pic6.jpg", "pic7.jpg", "pic8.jpg"];
var i = 1;
function changeImage() {
var image = document.getElementById('homeslideshow');
if (i < pics.length) {
image.src = pics[i]
i++;
}
else {
image.src = pics[i]
i = 0;
}
}
</script>
The function is called in the html with:
<body onload="setInterval(function(){changeImage()}, 4000)">
And the slideshow is displayed with:
<div id="section">
<img id="homeslideshow" src="pic1.jpg" alt="goofy" width="100%" height=auto>
</div>
I am a total newbie to html/css/js, so please be nice! Any help would be much appreciated.
Replace your else block as below
else {
i = 0;
image.src = pics[i];
}
as in your code, when you was setting the image.src before setting the value of i to 0, actually you were setting the image src with pics[8] which was not valid.
Also, you are missing a ; after image.src = pics[i] in the if block.
UPDATE
Replace your JS as below to solve your 8 seconds problem
<script>
var pics = ["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg", "pic5.jpg", "pic6.jpg", "pic7.jpg", "pic8.jpg"];
var i = 0;
function changeImage() {
var image = document.getElementById('homeslideshow');
if (i < pics.length-1) {
i++;
image.src = pics[i];
}
else {
i = 0;
image.src = pics[i];
}
}
</script>
You use 4000ms delay. Remove that.
setInterval(function(){changeImage()})

Change background image on pagescroll to create animation? Is canvas more efficient?

I am working on a parallax site in which there are sequence of images (around 400 images). The background images change based on page scroll to create a smoothly moving animation. I managed to get the scrolling working, but when the user scrolls, the change of background images are not smooth (We can see the blank space for a second or so depending on the internet connection). Also, the images are not being cached, the page does a new request every time. How can I optimize this code so that the animation is smooth and it doesn't request a new image every time and uses the cached images. Is it efficient to create the animation in canvas? I tried canvas, but it also makes a new request to images on every scroll. Here is my code using standard background changing based on page scroll:
HTML
<div class="container">
<div id="background-images" class="background-images">
<div class="test"></div>
</div>
</div>
CSS
#background-images{
height: 4000px;
}
.container{
border: 1px solid red;
height: 400px;
overflow: auto;
}
.test{
position: fixed;
top: 0;
left: 0;
z-index: 999;
width: 600px;
height: 600px;
}
Javascript
var $container = $(".container");
var $bgImage = $(".test");
// Attaching the scroll to the background image
$container.scroll(function(event) {
var position = $container.scrollTop();
setBgImage(position);
});
// preload the given total amount of iamges
function preload(totalImages) {
for (var i = 0; i < totalImages; i++) {
$('<img/>')[0].src = getImgUrl(i);
}
}
preload(36); // Preload 36 images, the cache should keep these so we wont't need to load these while we scroll
// Set the background image
function setBgImage(position){
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
console.log("IMG: " + imageNum + ", Position: " + position);
$bgImage.css("background-image", "url('" + getImgUrl(imageNum) + "')");
}
// Set a placeholder background image
function getImgUrl(num){
return "http://placehold.it/200x200/&text=" + num;
}
JSFiddle: http://jsfiddle.net/4j9u8qtf/1/
You could add all the images hidden and just show the correct one in an actual image element, instead of using css background image. I edited your jsfiddle to demonstrate:
function create(totalImages) {
for (var i = 0; i < totalImages; i++) {
var img = $('<img/>')
img[0].src = getImgUrl(i);
$bgImage.append(img)
}
setBgImage(0)
}
create(37);
function setBgImage(position){
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
console.log("IMG: " + imageNum + ", Position: " + position);
$bgImage.find("img").hide().eq(imageNum).show()
}
http://jsfiddle.net/y92g7vvL/1/
The best way to preload images is to use the Image constructor like the example below. Using the Image constructor makes it so you don't have to worry about attaching the images anywhere to the document to make them load.
function preload(url) {
var image = new Image();
image.src = url;
}
I updated your Fiddle to use this preload and to not use jQuery for setting the background-image. It works quite well now. All images are preloaded/loaded only once.
$(function () {
var $container = $(".container");
var $bgImage = $(".test");
var bgImage = $bgImage.get(0);
$container.scroll(function (event) {
var position = $container.scrollTop();
setBgImage(position);
});
// preload the given total amount of iamges
function preload(totalImages) {
function fetch(url) {
var image = new Image();
image.src = url;
}
for (var i = 0; i < totalImages; i++) {
fetch(getImgUrl(i));
}
}
preload(36);
function setBgImage(position) {
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
var url = getImgUrl(imageNum);
bgImage.style.backgroundImage = "url('"+ url +"')";
}
function getImgUrl(num) {
return "http://placehold.it/200x200/&text=" + num;
}
})
Try
html
<div class="container">
<div id="background-images" class="background-images">
<div class="test"></div>
</div>
</div>
<!-- hidden container for `img` elements -->
<div id="imgs"></div>
css
#imgs {
display:none;
}
js
$(function () {
var $container = $(".container");
var $bgImage = $(".test");
$container.scroll(function (event) {
var position = $container.scrollTop();
setBgImage(position);
});
// preload the given total amount of iamges
function preload(totalImages) {
for (var i = 0; i < totalImages; i++) {
$('<img/>', {
"src": getImgUrl(i)
})
// append `img` elements to `#imgs` container
// to `cache` the images ,
// images not requested again at
// `$bgImage` `background-image` adjustments
.appendTo("#imgs");
}
}
preload(36);
function setBgImage(position) {
var imageNum;
var lineCount = 0;
imageNum = parseInt(position / 100);
console.log("IMG: " + imageNum + "
, Position: " + position
, $("#imgs img[src$=" + imageNum + "]"));
// utilize images already in DOM ,
// load `#imgs img` `src` as `$bgImage` `background-image` ,
// from hidden `#imgs` `div`
// images _not_ requested again from server ,
// see `network` tab at console
$bgImage.css("background-image"
, "url('" + $("#imgs img[src$=" + imageNum + "]").attr("src") + "')");
}
function getImgUrl(num) {
return "http://placehold.it/200x200/&text=" + num;
}
});
jsfiddle http://jsfiddle.net/guest271314/bh91g0tv/
The reason that they're being requested over and over is that you're using jQuery background assignment, which reloads the image.
This is silly. You don't need or want jQuery here, and it has side effects you don't understand that are causing your problem.
Just set the X position of the background. Done.
function offset_to(id, posX, posY) {
document.getElementById(id).style.backgroundPosition = posX.toString() + 'px ' + posY.toString() + 'px';
}
To create a smooth effect to your image transition just add css transition in your case:-
.test{
-webkit-transition: all 0.5s ease;
-moz-transition: position 10s;
-ms-transition: position 10s;
-o-transition: position 10s;
transition: all 0.8s ease;
}

Uncaught TypeError: Cannot set property 'src' of undefined

url: http://www.gws-mbca.org
The slide show works in Firefox. It used to work in IE and Chrome. Now I get the following error in both IE and Chrome:
Uncaught TypeError: Cannot set property 'src' of undefined
The script is linked using a <script type="...> in the document head.
The code in the web page is as follows:
<section style="margin: 0 auto; text-align: center;">
<img src="./rPix/rp1.jpg" id="slide" width="900" height="200" alt="slide show images" />
</section>
<body onload="runShow();">
The function runShow is part of slideshow.js - Code is as follows:
/* An automatically rotating slide show using Javascript and the DOM.
This script cobbled together by Paul D.J. Vandenberg */
var j = 1;
var pix = new Array(11);
for (i = 0; i < pix.length; i++) {
pix[i] = "rPix/rp"+j+".jpg";
j++;
}
var index = Math.floor(Math.random() * 11) + 1;
var limit = pix.length - 1;
function runShow() {
if (index > limit) {
index = 0;
}
document.slide.src = pix[index];
setTimeout("runShow()", 10000);
index++;
}
Make sure you call runShow() after the id="slide" element has been added to the DOM.
document.slide is shorthand for document.getElementById("slide"). The latter will return null when no element with that id is defined.
The DOM must be loaded before the document can access any elements. Usually an onload event is used when the script is in the <head>
window.onload = function(){
var j = 1;
var pix = new Array(11);
for (i = 0; i < pix.length; i++) {
pix[i] = "rPix/rp"+j+".jpg";
j++;
}
var index = Math.floor(Math.random() * 11) + 1;
var limit = pix.length - 1;
window.runShow = function() {
if (index > limit) {
index = 0;
}
document.slide.src = pix[index];
setTimeout("runShow()", 10000);
index++;
}
};
"The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images and sub-frames have finished loading." -MDN
Suggested improvements
I thought I would throw this part in because there are few things I think you can improve here as far as your approach and decided to offer some suggestions.
Lets remove body onload="runShow()" from your code and make it just <body> or whatever other class etc you might have on there.
Lets also go in and use an interval instead of a timeout because for longrunning processes they are more accurate.
Also, lets try to remove all strings from the callbacks.
Example:
<html>
<head>
window.onload = function(){
var pix = [];//array to hold image source strings
var limit = 10;//0 based count for images
for( var i = 0; i < limit+1; i++ ){//runs 11 times
pix.push("rPix/rp"+(i+1)+".jpg";//push incrementally adds to pix array
}
var index = limit;//last index for image source in pix array
var slide = document.getElementById("slide");//cache slide image element
function runShow(){
if( index > limit ) index = 0;//cycle images by array length
slide.src = pix[index++];//change slide image using cached element
}
runShow();//run on load
setInterval(runShow,10000);//run every 10 seconds
};
</head>
<body>
<section style="margin: 0 auto; text-align: center;">
<img src="./rPix/rp1.jpg" id="slide" width="900" height="200" alt="slide show images" />
</section>
</body>
</html>
So here's what the code looks like now.
/* An automatically rotating slide show using Javascript and the DOM.
This script cobbled together by Paul D.J. Vandenberg with a nice
assist from stackoverflow */
window.onload = function() {
var j = 1;
var pix = new Array(11);
for (i = 0; i < pix.length; i++) {
pix[i] = "rPix/rp"+j+".jpg";
j++;
}
var index = Math.floor(Math.random() * 11) + 1; // Start at a random slide
var limit = pix.length - 1;
var slide = document.getElementById("slide"); // Cache slide image element
function runShow() {
if (index > limit) {
index = 0;
}
slide.src = pix[index++];
}
setInterval(runShow, 10000); // Interval more reliable than timeOut
runShow();
}

Displaying images like Google Image Search

Does anybody know of a script that will let me diplay image results in the way that Google Image Search does (image grid view) with hover to enlarge and details? Something that I can just "plug-and-play" so to speak.
Have a look at Masonry http://masonry.desandro.com/
First, you need to put all images inside a container element:
<div class="parent">
<img src="">
<img src="">
<img src="">
</div>
Then you need to make sure that the images are displayed in one line. This can be done by e.g. float: left. You should also set vertical-align to remove the small gap underneath each image:
img {
float: left;
vertical-align: top;
}
Finally you need some JavaScript to loop through all images and calculate the ideal rowHeight based on their dimensions. The only thing you need to tell this algorithm is the maximum row height that you want (rowMaxHeight)
// Since we need to get the image width and height, this code should run after the images are loaded
var elContainer = document.querySelector('.parent');
var elItems = document.querySelector('.parent img');
var rowMaxHeight = 250; // maximum row height
var rowMaxWidth = elContainer.clientWidth;
var rowWidth = 0;
var rowRatio = 0;
var rowHeight = 0;
var rowFirstItem = 0;
var rowIsLast = false;
var itemWidth = 0;
var itemHeight = 0;
// Make grid
for (var i = 0; i < elItems.length; i++) {
itemWidth = elItems[i].clientWidth;
itemHeight = elItems[i].clientHeight;
rowWidth += itemWidth;
rowIsLast = i === elItems.length - 1;
// Check if current item is last item in row
if (rowWidth + rowGutterWidth >= gridWidth || rowIsLast) {
rowRatio = Math.min(rowMaxWidth / rowWidth, 1);
rowHeight = Math.floor(rowRatio * rowMaxHeight);
// Now that we know the perfect row height, we just
// have to loop through all items in the row and set
// width and height
for (var x = rowFirstItem; x <= i; x++) {
elItems[i].style.width = Math.floor(rowRatio * itemWidth * (rowMaxHeight/itemHeight)) + 'px';
elItems[i].style.height = rowHeight + 'px';
}
// Reset row variables for next row
rowWidth = 0;
rowFirstItem = i + 1;
}
}
Note that this code is not tested and a very simplified version of what this vanilla JavaScript plugin does: https://fld-grd.js.org
Two solutions that I have found so far.
tutorial blog
jsfiddle
$(function() {
$(window).on('resize', function() {
$('.openEntry').remove();
$('.entry').hide();
var startPosX = $('.preview:first').position().left;
console.log(startPosX);
$('.entry, .preview').removeClass("first last");
$('.entry').each(function() {
if ($(this).prev('.preview').position().left == startPosX) {
$(this).prev('.preview').addClass("first");
$(this).prevAll('.entry:first').addClass("last");
}
});
$('.entry:last').addClass("last");
});
$(window).trigger('resize');
$('.trigger').click(function() {
$('.openEntry').slideUp(800);
var preview = $(this).closest('.preview');
preview.next('.entry').clone().addClass('openEntry').insertAfter(preview.nextAll('.last:first')).slideDown(800);
});
$('body').on('click', '.close', function() {
$('.openEntry').slideUp(800).remove();
});
})
codrops actually puts the photo enlargement/details inline instead of as a modal overlay:
http://tympanus.net/codrops/2013/03/19/thumbnail-grid-with-expanding-preview/
This might be what you are looking for... http://www.gethifi.com/demos/jphotogrid
Have a look at the gPop plugin
DEMO
Download in Github
Check out this jQuery Plugin: https://github.com/brunjo/rowGrid.js
It places images like on the Google image search.
Simply just repeat your images like this:
<img style="float: left; height: 12em; margin-right: 1%; margin-bottom: 0.5em;border:1px solid lightgray" src="ImgSrc " />

Categories

Resources