Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I want to turn the banner image on this page into a slide show. I know how to write HTML and CSS but I'm less adept at scripting.
My idea is to have the text stay in place while the the banner image behind it is replaced. I would like to see the new image fade in.
How can I implement this with JavaScript or jQuery?
I implemented a simple fade-out/fade-in slide show for you. The demonstration below uses the three large files you specified in your comments. The slide show won't work until the images have been loaded, so you may want to work on improving the load times.
To use this slide show in your project, merge the CSS rules below into your CSS file, then insert the JavaScript into your page and modify the parameters slideDelay, fadeLength, and imageSources to suit your needs.
SlideShow = {
slideDelay: 5, // Number of seconds to wait before showing a new slide.
fadeLength: 1, // Number of seconds to spend fading in or fading out.
hertz: 60 // Number of times per second to update the fade effect.
};
SlideShow.imageSources = [
'http://preview.impactdesigns-ad.com/HBP/img/basecamp009.jpg',
'http://preview.impactdesigns-ad.com/HBP/img/biohazard007.jpg',
'http://preview.impactdesigns-ad.com/HBP/img/Header.png'
];
SlideShow.showSlide = function (newImage, oldImage) {
var g = SlideShow,
opacityIncrement = 1 / g.hertz,
fade = { interval: {}, count: {} };
function fadeOut() { // Gradually makes the old image vanish.
oldImage.style.opacity = fade.count.out * opacityIncrement;
if (--fade.count.out == 0) {
window.clearInterval(fade.interval.out);
oldImage.style.visibility = 'hidden';
}
}
function fadeIn() { // Gradually makes the new image appear.
newImage.style.opacity = 1 - fade.count.in * opacityIncrement;
if (--fade.count.in == 0) {
window.clearInterval(fade.interval.in);
}
}
function newSlide() { // Starts the fade-in process.
newImage.style.opacity = 0;
newImage.style.visibility = 'visible';
fade.count.in = g.hertz;
fade.interval.in = window.setInterval(fadeIn, g.fadeLength * 1000 / g.hertz);
}
if (oldImage) { // Fade out the old, then fade in the new.
window.setTimeout(newSlide, g.fadeLength * 1000);
fade.count.out = g.hertz;
fade.interval.out = window.setInterval(fadeOut, g.fadeLength * 1000 / g.hertz);
} else { // If there is no old image, immediately fade in the new image.
newSlide();
}
}
SlideShow.replaceSlide = function () { // Updates slideIndex and calls showSlide.
var g = SlideShow,
images = g.images,
oldImage = images[g.slideIndex];
g.slideIndex = ++g.slideIndex % images.length;
var newImage = images[g.slideIndex];
g.showSlide(newImage, oldImage);
};
SlideShow.stop = function () {
var g = SlideShow,
interval = g.interval;
window.clearInterval(interval);
}
SlideShow.start = function () {
var g = SlideShow,
imageSources = g.imageSources,
images = g.images = [],
container = document.getElementById('slideContainer'),
background = g.background = document.createElement('div');
background.className = 'background';
for (var i = 0; i < imageSources.length; ++i) {
var image = document.createElement('img');
image.src = imageSources[i];
image.style.visibility = 'hidden';
images.push(image);
background.appendChild(image);
}
container.appendChild(background);
var startInterval = window.setInterval(function () {
for (var i = 0; i < images.length; ++i) {
if (images[i].height == 0) { // Wait until all images are loaded.
return;
}
}
window.clearInterval(startInterval);
g.slideIndex = 0;
g.showSlide(images[g.slideIndex]);
g.interval = window.setInterval(g.replaceSlide, g.slideDelay * 1000);
}, 100);
};
SlideShow.start();
#slideContainer {
font-family: sans-serif;
font-weight: bold;
font-style: italic;
font-size: 48px;
color: #cb4949;
width: 1000px;
height: 700px;
overflow: hidden;
position: relative;
}
#slideContainer span {
padding: 20px;
text-align: center;
position: absolute;
z-index: 10;
}
#slideContainer .background, #slideContainer .background img {
position: absolute;
left: 0;
top: 0;
}
<div id="slideContainer"> <span>This is some text over the slide.</span> </div>
<button onclick="SlideShow.stop()"> stop slide show </button>
Related
I have a script which changes the background-img property of multiple divs, every 20ms.
var frames = ["57.png", "59.png", "60.png"]
var currentframe = 0;
var frame_loop = setInterval(function () {
if (currentframe == 3) {
currentframe = 0;
} else {
for (var i = 0; i < $(".my-element").length; i++) {
$(`.my-element:nth-child(${i + 1})`).css("background-image", `url(assets/loop/${frames[currentframe]})`);
}
currentframe++;
}
}, 20);
The script above works as it should, however I experience some performance issues - and i'm assuming it's because the background-img is changing quite fast.
Is there anyway I could fix this issue? I don't mind using libraries. Would I need to resort to using gifs? Is it possible to use gifs with background-img?
Thanks for any feedback.
Here is an example of how I would do it (may not be the most performant, but might help):
var frames = [
"https://a.wattpad.com/useravatar/Kitten6416.256.440418.jpg",
"https://i.pinimg.com/474x/b5/e1/be/b5e1bef76b2058910f556c85c1040b79.jpg",
"https://a.wattpad.com/useravatar/Vendedora_De_Meng.128.220869.jpg"
];
var currentFrame = 0,
loopRunning = confirm("Warning! This page might trigger epileptic seizures. Continue?"),
// Don't calculate those every time
elems = document.querySelectorAll('.my-element'),
nbElems = elems.length;
(function frame_loop() {
if (loopRunning) {
// Calculate this once before the loop
var background = `url(${frames[currentFrame]})`;
for (var i = 0; i < nbElems; i++) {
elems[i].style.backgroundImage = background;
}
currentFrame = ++currentFrame % nbElems;
requestAnimationFrame(frame_loop);
}
})();
.my-element {
display: inline-block;
width: 100px;
height: 100px;
background-size: cover;
background-position: center;
}
<div class="my-element"></div>
<div class="my-element"></div>
<div class="my-element"></div>
i have this code here for sliding images but i wanted to do the same thing for sliding text instead of images but it is not working with me when i tried it , so any one can do it for me text slider moving from left to right instead of image slider without mouse click? and thanks in advance
var mainImage = document.getElementById("mainImage");
//Create image array
var imageArray = ["Life is what happens to us while we are making other plans","Life is what happens to us while we are making other plans","Life is what happens to us while we are making other plans"];
//Set up array index
var imageIndex = 0;
function changeImage() {
mainImage.setAttribute("src",imageArray[imageIndex]);
imageIndex++;
if(imageIndex >= imageArray.length) {
imageIndex = 0;
}
}
//Create function to cycle through images
mainImage.onclick = changeImage
//Call cycle function
var intervalHandle = setInterval(changeImage,3000);
mainImage.onclick = function () {
clearInterval(intervalHandle);
}
h1 {
text-align: center;
}
#mainImage {
padding-left: 350px;
padding-top: 40px;
}
//<img id="mainImage" src="images/D.png" />
You need to use HTML DOM innerHTML Property.
Create an element with id="text" change document.getElementById("text").innerHTML
var textElement = document.getElementById("text");
//Create image array
var imageArray = ["Life is what happens to us while we are making other plans","Life is what happens to us while we are making other plans2","Life is what happens to us while we are making other plans3"];
//Set up array index
var imageIndex = 0;
function changeImage() {
textElement.innerHTML = imageArray[imageIndex]
imageIndex++;
if(imageIndex >= imageArray.length) {
imageIndex = 0;
}
}
//Create function to cycle through images
textElement.onclick = changeImage
//Call cycle function
var intervalHandle = setInterval(changeImage,3000);
textElement.onclick = function () {
clearInterval(intervalHandle);
}
h1 {
text-align: center;
}
#mainImage {
padding-left: 350px;
padding-top: 40px;
}
<p id="text"></p>
I am trying to create an image carousel and I want the images to loop through the array. The code is clearly working because the "no click" alert shows but I don't understand what I am doing wrong.
Here is JS. I know the problem is most likely the if statement. I'm a beginner in JS and haven't quite understood how to code that bit properly. In some sort of pseudo code, it would ideally be "if btn is clicked, then show the next image".
let images = ["img1.jpg", "img2.jpg", "img3.jpg"];
let img = images.length;
let x = 0;
function whenClicked(e) {
for (let i = 0; i < img; i++) {
if (x == 0) {
document.getElementById("img1").style.backgroundImage = ++img;
} else alert("no click!")
}
}
const btnLeft = document.getElementById("btn-left");
const btnRight = document.getElementById("btn-right");
btnLeft.addEventListener("click", whenClicked);
btnRight.addEventListener("click", whenClicked);
And here HTML.
<div class="slide-container">
<div class="slide" id="img1">
<i class="fas fa-arrow-circle-left fa-3x" id="btn-left" ></i>
<i class="fas fa-arrow-circle-right fa-3x" id="btn-right" ></i>
</div>
</div>
CSS.
.slide-container {
}
.slide {
height: 789px;
width: 100%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.slide:nth-child(1) {
background-image: url(../img/img1.jpg);
}
.slide:nth-child(2) {
background-image: url(../img/img2.jpg);
}
.slide:nth-child(3) {
background-image: url(../img/img3.jpg);
}
#btn-left {
position: absolute;
top: 400px;
}
#btn-right {
position: absolute;
left: 1380px;
top: 400px;
}
Suggestions on what to do to improve would be deeply appreciated!
You might be overcomplicating your approach. Try to keep track of which image is currently being shown and what image should be next. You are almost doing this, with I assume is your intent, with the x variable. This is a great way to select an image from the array by simply doing images[x], which translates to images[0] at the start.
So if you want to develop a system which changes the background image of the slide, then your buttons would have to change the value of the x variable. Let's give that variable a more clear name, like currentIndex which represents the current index in the images array. Or to be clear, the current image we are seeing.
When your right button is clicked, you'll want the next image. The next images in the images array is images[1]. All you have to do is update the currentImage value with +1 or ++ and select the next image with images[currentIndex] to get the next one.
Same goes for the left button which should remove 1 from the currentImage with either -1 or -- to go back one index in the images array. Then select the image the same way with images[currentIndex].
Now for both these buttons you'll need to check if you go past the start or the end of the images array. currentIndex cannot be lower than 0 and with 3 images in the array, the currentIndex value should not be higher than 2, since we are counting with [0, 1, 2] in the images array.
Below I've made an implementation of this system. I hope this is what you intended to make. If I haven't been clear or you have question, then don't hesitate to ask.
let images = ["img1.jpg", "img2.jpg", "img3.jpg"];
let amountOfImages = images.length;
let currentIndex = 0;
const slide = document.getElementById("img1");
const btnLeft = document.getElementById("btn-left");
const btnRight = document.getElementById("btn-right");
function prevImage() {
if (currentIndex > 0) { // Can't go lower than 0.
currentIndex--;
updateImage();
}
}
function nextImage() {
if (currentIndex < amountOfImages - 1) { // Can't go higher than the amount of images present.
currentIndex++;
updateImage();
}
}
function updateImage() {
slide.style.backgroundImage = images[currentIndex];
}
btnLeft.addEventListener("click", prevImage);
btnRight.addEventListener("click", nextImage);
let currentImage = 0;
let images = ["img1.jpg", "img2.jpg", "img3.jpg"];
function whenClicked(e) {
if(e.target.id == 'btn-left') {
currentImage--;
} else {
currentImage++;
}
if(currentImage > images.length-1) {
currentImage = 0;
}
if(currentImage < 0) {
currentImage = images.length-1;
}
document.getElementById("img1").style.backgroundImage = url('img/'+images[currentImage]);
}
PURE JS ONLY PLEASE - NO JQUERY
I have a div with overflow scroll, the window (html/body) never overflows itself.
I have a list of anchor links and want to scroll to a position when they're clicked.
Basically just looking for anchor scrolling from within a div, not window.
window.scrollTo etc. don't work as the window never actually overflows.
Simple test case http://codepen.io/mildrenben/pen/RPyzqm
JADE
nav
a(data-goto="#1") 1
a(data-goto="#2") 2
a(data-goto="#3") 3
a(data-goto="#4") 4
a(data-goto="#5") 5
a(data-goto="#6") 6
main
p(data-id="1") 1
p(data-id="2") 2
p(data-id="3") 3
p(data-id="4") 4
p(data-id="5") 5
p(data-id="6") 6
SCSS
html, body {
width: 100%;
height: 100%;
max-height: 100%;
}
main {
height: 100%;
max-height: 100%;
overflow: scroll;
width: 500px;
}
nav {
background: red;
color: white;
position: fixed;
width: 50%;
left: 50%;
}
a {
color: white;
cursor: pointer;
display: block;
padding: 10px 20px;
&:hover {
background: lighten(red, 20%);
}
}
p {
width: 400px;
height: 400px;
border: solid 2px green;
padding: 30px;
}
JS
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p'),
main = document.querySelector('main');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(){
var linkID = this.getAttribute('data-goto').slice(1);
for (var j = 0; j < links.length; j++) {
if(linkID === paras[j].getAttribute('data-id')) {
window.scrollTo(0, paras[j].offsetTop);
}
}
})
}
PURE JS ONLY PLEASE - NO JQUERY
What you want is to set the scrollTop property on the <main> element.
var nav = document.querySelector('nav'),
main = document.querySelector('main');
nav.addEventListener('click', function(event){
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
main.scrollTop = scrollTarget.offsetTop;
}
});
You'll notice a couple of other things I did different:
I used event delegation so I only had to attach one event to the nav element which will more efficiently handle clicks on any of the links.
Likewise, instead of looping through all the p elements, I selected the one I wanted using an attribute selector
This is not only more efficient and scalable, it also produces shorter, easier to maintain code.
This code will just jump to the element, for an animated scroll, you would need to write a function that incrementally updates scrollTop after small delays using setTimeout.
var nav = document.querySelector('nav'),
main = document.querySelector('main'),
scrollElementTo = (function () {
var timerId;
return function (scrollWithin, scrollTo, pixelsPerSecond) {
scrollWithin.scrollTop = scrollWithin.scrollTop || 0;
var pixelsPerTick = pixelsPerSecond / 100,
destY = scrollTo.offsetTop,
direction = scrollWithin.scrollTop < destY ? 1 : -1,
doTick = function () {
var distLeft = Math.abs(scrollWithin.scrollTop - destY),
moveBy = Math.min(pixelsPerTick, distLeft);
scrollWithin.scrollTop += moveBy * direction;
if (distLeft > 0) {
timerId = setTimeout(doTick, 10);
}
};
clearTimeout(timerId);
doTick();
};
}());
nav.addEventListener('click', function(event) {
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
scrollElementTo(main, scrollTarget, 500);
}
});
Another problem you might have with the event delegation is that if the a elements contain child elements and a child element is clicked on, it will be the target of the event instead of the a tag itself. You can work around that with something like the getParentAnchor function I wrote here.
I hope I understand the problem correctly now: You have markup that you can't change (as it's generated by some means you have no control over) and want to use JS to add functionality to the generated menu items.
My suggestion would be to add id and href attributes to the targets and menu items respectively, like so:
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p');
for (var i = 0; i < links.length; i++) {
links[i].href=links[i].getAttribute('data-goto');
}
for (var i = 0; i < paras.length; i++) {
paras[i].id=paras[i].getAttribute('data-id');
}
I am trying to write a function that will change between an array of images. What I have makes sense to me, but when I run it as it is below then the first image loads, then the second image loads at some point (the transparency doesn't change) and then nothing happens. Here is the javascript code:
var image1 = new Image();var image2 = new Image(); var image3 = new Image();
image1.src = "images/website6.jpg"; image2.src = "images/website7.jpg"; image3.src = "images/sunset.jpg";
var images = new Array("images/website6.jpg","images/website7.jpg","images/sunset.jpg");
/*document.slide.style.opacity = 1;
document.slide.stylebg.opacity = 0;*/
setTimeout(function() { fade(images,0); }, 2000);
function delay(arr,num)
{
document.slide.src = arr[num % 3];
document.slide.style.opacity = 1;
document.slidebg.style.opacity = 0;
document.slidebg.src = arr[(num+1)%3];
var number = num + 1;
setTimeout(function() { fade(arr,number); }, 2000);
}
function fade(arr,num)
{
/*alert('fadebefore ' + (document.slide.style.opacity).toString())*/
document.slide.style.opacity -= 0.1
/*alert('fade')*/
document.slide.stylebg.opacity += 0.1
if (document.slide.style.opacity == 0)
{
setTimeout(function() { delay(arr,num); }, 150);
}
else
{
setTimeout(function() { fade(arr,num); }, 1500);
}
}
The HTML is simple. I have two classes; style and stylebg. style sits in front of stylebg and then I change opacities and images as needed. The javascript seems logical to me, but it doesn't work as expected. Also worth noting is there are 3 comments. The first comment (line 3-4) is attemping to set the opacities to what they should be at the beginning. However, if I do this then I get even less progress than above: the first image loads and nothing else happens. The second two comments are used for debugging purposes. If I uncomment these then the image change occurs between the two alerts, which would seem to say the image change is caused by the opacity change.
So can anybody explain why it isn't doing what I expect it to? Thanks.
EDIT: Some more code:
HTML (This is the only part being affected):
<div style="position: relative;">
<img src="images/sunset.jpg" id="slide" />
<img src="images/website6.jpg" id="slidebg" />
</div>
CSS:
#slide{
display:block;
margin-left:5;
margin-right:auto;
border: 1px solid black;
z-index: 1;
top: 0px;
position: relative;
}
#slidebg{
display:block;
margin-left:auto;
margin-right:auto;
border: 1px solid black;
z-index: 0;
top: 0px;
position: absolute;
}
Answering for formatting's sake. I have not debugged to see what would work, but this makes more sense to me
If you want to use ID, use document.getElementById, if you want to use name, use document.images[imgname] or document.imagename
You are mixing names and style too. document.slide.stylebg.opacity and such
This does something. Not sure it is what you want: http://jsfiddle.net/EcShW/2/
<div style="position: relative;">
<img src="images/sunset.jpg" id="slide" name="slide" />
<img src="images/website6.jpg" id="slidebg" name="slidebg" />
</div>
var images = []; // can be more elegant, but this is simpler
images[0]=new Image(); images[0].src="images/website6.jpg";
images[1]=new Image(); images[1].src="images/website7.jpg";
images[2]=new Image(); images[2].src="images/sunset.jpg";
var tid1,tid2,tid3
tid1=setTimeout(function() { fade(images,0); }, 2000);
function delay(arr,num)
{
document.slide.src = arr[num % 3].src;
document.slide.style.opacity = 1;
document.slidebg.style.opacity = 0;
document.slidebg.src = arr[(num+1)%3].src;
var number = num + 1;
tid2=setTimeout(function() { fade(arr,number); }, 2000);
}
function fade(arr,num)
{
document.slide.style.opacity -= 0.1
document.stylebg.style.opacity += 0.1
if (document.slide.style.opacity == 0)
{
tid3=setTimeout(function() { delay(arr,num); }, 150);
}
else
{
tid3=setTimeout(function() { fade(arr,num); }, 1500);
}
}
You can't just refer to page elements by "id" value like that; you have to use "document.getElementById()":
var slideElement = document.getElementById('slide'), slidebgElement = document.getElementById('slidebg');
Then you'd work with "slideElement.style" etc. instead of "document.slide.style".
EDIT2
It works for me (chromium)
var images = new Array ();
images[0] = new Image();
images[0].src = "images/website6.jpg";
images[1] = new Image();
images[1].src = "images/website7.jpg";
images[2] = new Image();
images[2].src = "images/sunset.jpg";
function delay ( arr, num )
{
slide.src = arr[num % 3].src;
slide.style.opacity = 1;
slidebg.style.opacity = 0;
slidebg.src = arr[(num+1)%3].src;
var number = num + 1;
setTimeout(function() { fade(arr,number); }, 2000);
}
function fade(arr, num)
{
if ( slide.style.opacity == 0 )
setTimeout(function (){ delay(arr, num); }, 150);
else
{
slide.style.opacity = (slide.style.opacity*10 - 1)/10 ;
slidebg.style.opacity -= -0.1;
setTimeout ( function(){fade(arr,num);}, 1500 );
}
}
fade (images, 0);
AHA!
<img id="img_id"/> we can get by document.img_id, even in chromium
OK, OK, removed links to this WE TEACH YOU TO FAIL AT WEB DEV site..