This one is driving me crazy. My javascript code works for most slides in a deck I create but sometimes it messes up. It usually takes one of four forms:
the slide will appear as a tiny picture under a logo I put on the slide when the slide isn't wide enough to fill the viewing area, or
the slide will appear properly sized but under the logo which now occupies the full height of the viewing area, or
both of the above, or
neither the slide nor the logo appear. Instead the previous slide continues to be shown.
My code isn't all that complicated. The part that shows the individual slide is below:
var backgroundImage;
var imgHeight;
var imgWidth;
function waitForHeight() {
sleep(120).then(() => {
if (imgHeight == 0) {
waitForHeight()
} else {
setBackground();
}
});
}
function getSizes() {
imgHeight = this.height;
imgWidth = this.width;
return true;
}
function showImage(imgPath) {
var myImage = new Image();
myImage.name = imgPath;
myImage.onload = getSizes;
myImage.src = imgPath;
return myImage;
}
function setBackground() {
var backgroundPosition = "";
var backgroundSize = "100%";
var aspectRatio = imgHeight / imgWidth;
if (aspectRatio > 0.70) {
backgroundSize = "10vw, auto 100%";
backgroundImage = "URL(images/LCI_emblem_2color.png), " + backgroundImage;
backgroundPosition = "top 1rem left 1rem, top right";
}
var mainPanel = document.getElementById("mainpanel")
mainPanel.style.backgroundImage = backgroundImage;
mainPanel.style.backgroundPosition = backgroundPosition;
mainPanel.style.backgroundSize = backgroundSize;
}
function addPic(curCell, curSlide, nodeNum) {
imgHeight = 0; // flag that height not set yet
var curImg = showImage(curSlide.childNodes[nodeNum].firstChild.nodeValue);
curImg.setAttribute('class', 'd-none d-md-block');
curCell.appendChild(curImg);
backgroundImage = "URL(" + getSlidePicture(curSlide) + ")";
waitForHeight();
}
The code, as I said, is not complicated. I can understand somewhat what the problem is - either the picture doesn't load or it gets put into the wrong "background" area, but I don't get why it happens.
I've noted the issue occurs with the same slides in both Chromium and Firefox and has survived multiple versions of each browser, so it's probably not a browser issue.
Any ideas?
Related
I just adapted this code to play a sequence of images when you move the mouse on the x axis. I have two questions about this code:
I can't adapt the length to the width of the div, not to the width of the whole window.
There are "flashes" when I move the mouse, I have the impression that it comes from the loading of the images?
Thanks for your help.
Live: https://codepen.io/nicolastilly/pen/jOBKxKK
Code:
var blocWidth;
var imgblock = ['https://assets.codepen.io/265602/frame0.png',
'https://assets.codepen.io/265602/frame1.png',
'https://assets.codepen.io/265602/frame2.png',
'https://assets.codepen.io/265602/frame3.png',
'https://assets.codepen.io/265602/frame4.png',
'https://assets.codepen.io/265602/frame5.png',
'https://assets.codepen.io/265602/frame6.png',
'https://assets.codepen.io/265602/frame7.png',
'https://assets.codepen.io/265602/frame8.png',
'https://assets.codepen.io/265602/frame9.png',
'https://assets.codepen.io/265602/frame10.png',
'https://assets.codepen.io/265602/frame11.png',
'https://assets.codepen.io/265602/frame12.png',
'https://assets.codepen.io/265602/frame13.png',
'https://assets.codepen.io/265602/frame14.png',
'https://assets.codepen.io/265602/frame15.png',
'https://assets.codepen.io/265602/frame16.png',
'https://assets.codepen.io/265602/frame17.png',
'https://assets.codepen.io/265602/frame18.png',
'https://assets.codepen.io/265602/frame19.png',
'https://assets.codepen.io/265602/frame20.png'];
function onMouseMove(e) {
var x = e.pageX;
var theimg = imgblock[parseInt(x / blocWidth * imgblock.length)];
$('.bloc1').css("background-image", "url('" + theimg + "')");
}
function onResize() {
blocWidth = $('.bloc1').width();
}
function onResize() {
blocWidth = $(document).width();
}
$(window).on('mousemove', onMouseMove);
$(window).resize(onResize);
onResize();
As for flickering, you can circumvent that by preloading the images
let loaded = 0 ;
imgblock.forEach(url => {
let img=new Image();
img.src=url;
img.onload = onImgLoaded
})
function onImgLoaded() {
loaded++;
if (loaded == imgblock.length-1) console.log('all images have pre-loaded');
}
As for the sizing issue, you need to take into account if you're mousing over the target and accounting for the div's left value in your calculations. Get rid of both these:
function onResize() {
blocWidth = $('.bloc1').width();
}
function onResize() {
blocWidth = $(document).width();
}
replace with:
let blocStartX;
function onResize() {
let pos = $(".bloc1")[0].getBoundingClientRect()
console.log(pos)
blocWidth = pos.width;
blocStartX = pos.x
}
Detect the mouseover:
let isOnDiv = false
$(".bloc1").mouseenter(function(){isOnDiv=true;});
$(".bloc1").mouseleave(function(){isOnDiv=false;});
and add this to the top of your mousemove function:
if (!isOnDiv) return
var x = e.pageX - blocStartX;
https://codepen.io/john-tyner/pen/wvJXXQZ
I want to implement sliding images as soon as the website loads.
Here's my html code
<html>
<title>Wold of Guitars</title>
<body onload="images()">
</body>
</html>
And here's my javascript
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[0].src = '../img/n/h1.jpg';
imgArray[1] = new Image();
imgArray[1].src = '../img/n/h2.jpg';
imgArray[2] = new Image();
imgArray[2].src = '../img/n/home.jpg';
imgArray[3] = new Image();
imgArray[3].src = '../img/n/h3.jpg';
imgArray[4] = new Image();
imgArray[4].src = '../img/n/h4.jpg';
x=-1;
function images()
{ x=x+1
if(x>4)
x=1
document.write("<li><img src='" + imgArray[x] + "' width="1350" height="630"/><span>" + imgArray[] + "</span></li>");
var t=setInterval("images()",3000);
}
Help will be appreciated.
Although you mentioned "sliding" your initial code looked liked you wanted to swap the images over time.
I admit you may struggle to find good resources on JavaScript for something so simple, which Is why I can relate to your question.
Ok so here's a quick & dirty but more modern-ish image changing slide requestAnimationFrame:
https://jsfiddle.net/julienetienne/95tqftnk/4/
The same principals apply for making images slide except you are pre-loading all images and shifting the position by the slide show width.
var speed = 3;
// Your image array
var images = [
'http://www.gettyimages.co.uk/gi-resources/images/Homepage/Category-Creative/UK/UK_Creative_462809583.jpg',
'http://www.hdwallpapersimages.com/wp-content/uploads/images/Child-Girl-with-Sunflowers-Images.jpg',
'http://www.gettyimages.co.uk/CMS/StaticContent/1391099215267_hero2.jpg'];
// Get the slideShow tag
var slideShow = document.getElementById('slide-show');
// Create the image tag //You could also just make one in HTML and get the tag
var img = document.createElement('img');
// Append the image to the slideshow container
slideShow.appendChild(img);
// Basic request animation polyfill
var rAF = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
return setTimeout(callback, 1000 / 60);
};
// declare var count outside of rAF loop
var count;
function changeImage(timeStamp) {
count = Math.floor(timeStamp / 1000 / speed);
while (count > images.length -1) {
count -= images.length;
}
img.src = images[count];
rAF(changeImage);
}
rAF(changeImage);
img {
width: 600px;
height auto;
}
<div id="slide-show"></div>
I need auto scrolling image placed inside a div. I saw a code for horizontal auto scroll on this page
http://www.dynamicsights.com/cssscrollback.php
I modified it a little to turn it into vertical auto scroll, but for some reason it stopped working. Can someone please tell me what I did wrong, and is there easier way to make vertical auto scroll?
<div id="scroller"></div>
css:
#scroller
{
width:250px; height:120px;
background-image:url(images/background.png); /* size of that image is 250x600 */
}
js:
function StartMove()
{
var BGImage = new Image();
BGImage.src = "images/background.png";
window.cssMaxHeight = 600;
window.cssYPos = 0;
setInterval("MoveBackGround()", 50);
}
function MoveBackGround()
{
window.cssYPos ++;
if (window.cssYPos >= window.cssMaxHeight)
{
clearInterval(MoveBackGround())
}
toMove=document.getElementById("scroller");
toMove.style.backgroundPosition="0 "+window.cssYPos+"px";
}
Code has so many global variables and removing the interval is wrong.
(function() {
var cssMaxHeight, cssYPos, interval, moveTo;
function MoveBackGround() {
cssYPos++;
if (cssYPos >= cssMaxHeight) {
window.clearInterval(interval);
}
toMove = document.getElementById("scroller");
toMove.style.backgroundPosition = "0 " + cssYPos + "px";
}
function StartMove() {
var BGImage = new Image();
BGImage.src = "images/background.png";
cssMaxHeight = 600;
cssYPos = 0;
interval = setInterval(MoveBackGround, 50);
}
StartMove();
}());
I have a image on the website.
i should get the CSS value of Max_width for that image using java script for my Jasmine framework.
Can you please guid me.
Here is the code:
it("Should return Max-width value: '"+width+"'",function(){
var width, item;
item = OpenSpace.getElementById("OpenLayers.Layer.Vector_49_svgRoot");
width = item.max_width;
expect(result).toBe(width);
alert(width);
Thanks
Ravi
clientWidth is the inner width of an element in pixels. It includes padding but not the vertical scrollbar (if present, if rendered), border or margin.
var img = document.getElementById('imageid');
var width = img.clientWidth;
Another solution:
var img = new Image();
img.onload = function() {
alert(this.width + 'x' + this.height);
}
img.src = 'http://www.google.com/intl/en_ALL/images/logo.gif';
Hope it works
I've figured out the centering and resizing issues, but I still can't get onLoad to work properly. Anyone have any ideas? I thought onLoad was supposed to wait for the image to be loaded completely before firing the code. As this is right now, it resizes the img for the next img, and fades it in before it's loaded, so the previous image fades in again. Once the show has run through once, it works perfectly, so obviously it's not waiting for the image to load completely before firing imageLoad().
<div id="slideShow">
<div id="slideShowImg" style="display:none; margin-right:auto; margin-left:auto;">
</div>
<div id="slideShowThumbs">
</div>
<script type="text/javascript">
loadXMLDoc('http://www.thehoppr.com/hopspots/82/82.xml', function() {
var slideShow = document.getElementById('slideShow');
var items = [];
var nl = xmlhttp.responseXML.getElementsByTagName('image');
var i = 0;
var t;
var slideShowImg = document.getElementById('slideShowImg');
var slideShow = document.getElementById('slideShow');
var maxHeight = 300;
var maxWidth = 800;
var imgNode = new Image();
function image() {
var nli = nl.item(i);
var src = nli.getAttribute('src').toString();
var width = parseInt(nli.getAttribute('width').toString());
var height = parseInt(nli.getAttribute('height').toString());
imgNode.onLoad = imageLoad();
imgNode.src = src;
imgNode.height = height;
imgNode.width = width;
imgNode.setAttribute("style", "margin-right:auto; margin-left:auto; display:block;");
var ratio = maxHeight / maxWidth;
if (imgNode.height / imgNode.width > ratio) {
// height is the problem
if (imgNode.height > maxHeight) {
imgNode.width = Math.round(imgNode.width * (maxHeight / imgNode.height));
imgNode.height = maxHeight;
}
} else {
// width is the problem
if (imgNode.width > maxHeight) {
imgNode.height = Math.round(imgNode.height * (maxWidth / imgNode.width));
imgNode.width = maxWidth;
}
}
}
function imageLoad() {
slideShowImg.appendChild(imgNode);
Effect.Appear('slideShowImg', {
duration: 1
});
t = setTimeout(nextImage, 7000);
}
function nextImage() {
slideShowImg.setAttribute("style", "display:none");
if (i < nl.length - 1) {
i++;
image();
} else {
i = 0;
image();
}
}
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//XML Loaded, create the slideshow
alert(xmlhttp.responseText);
image();
}
});
</script>
Here are some of my thoughts (it's all open discussion)...
Preloading - Since you're limited to downloading 2 resources in parallel per hostname, it may not make sense to preload everything up front. Since it's a slideshow, how about modifying image() to download the i + 1 image through an Image object that doesn't get appended to the DOM? It doesn't seem beneficial to prefetch i + 2 and beyond in a slideshow setting.
Centering the images - Regarding using the auto margin width for horizontal centering, I believe you'll have to explicitly set the image to display:block. Obviously that doesn't solve centering vertically. Are all the images the same size? Also, will the slideShowImg div have a defined height/width? If so, then some math can be applied to achieve the centering.
Hope this helps! :)
Ok so I fixed the issue with the onLoad, and I even added a little preloading to help the slideshow along as well. All I had to do was define the onload first, and then do everything else except define the src inside the onload's function. I then added a little nextImg preloading so there's little if no hiccup between images even if it's the first time the browser is loading them. Here's the final code for anyone who has similar onload issues and finds there way here:
<div id="slideShow">
<div id="slideShowImg" style="display:none; margin-right:auto; margin-left:auto;">
</div>
<div id="slideShowThumbs">
</div>
<script type="text/javascript">
loadXMLDoc('/82.xml', function() {
var slideShow = document.getElementById('slideShow');
var items = [];
var nl = xmlhttp.responseXML.getElementsByTagName('image');
var i = 0;
var t;
var slideShowImg = document.getElementById('slideShowImg');
var slideShow = document.getElementById('slideShow');
var maxHeight = 300;
var maxWidth = 800;
var curImg = new Image();
var nextImg = new Image();
function image() {
var cli = nl.item(i);
var src = cli.getAttribute('src').toString();
var width = parseInt(cli.getAttribute('width').toString());
var height = parseInt(cli.getAttribute('height').toString());
curImg.onload = function() {
curImg.height = height;
curImg.width = width;
curImg.setAttribute("style", "margin-right:auto; margin-left:auto; display:block;");
slideShowImg.appendChild(curImg);
var ratio = maxHeight / maxWidth;
if (curImg.height / curImg.width > ratio) {
// height is the problem
if (curImg.height > maxHeight) {
curImg.width = Math.round(curImg.width * (maxHeight / curImg.height));
curImg.height = maxHeight;
}
} else {
// width is the problem
if (curImg.width > maxHeight) {
curImg.height = Math.round(curImg.height * (maxWidth / curImg.width));
curImg.width = maxWidth;
}
}
}
curImg.src = src;
if (i < nl.length - 1) {
var nli = nl.item(i + 1);
var nsrc = nli.getAttribute('src').toString();
nextImg.src = nsrc;
}
Effect.Appear('slideShowImg', {
duration: 1
});
t = setTimeout(nextImage, 7000);
}
function imageLoad() {}
function nextImage() {
slideShowImg.removeChild(curImg);
slideShowImg.setAttribute("style", "display:none");
if (i < nl.length - 1) {
i++;
image();
} else {
i = 0;
image();
}
}
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//XML Loaded, create the slideshow
alert(xmlhttp.responseText);
image();
}
});
</script>