简体   繁体   中英

Background Image Transition

I am trying to get my background "jumbotron" to change images. It works, however, I would like to add a transition to the image background as it is pretty rough. I was hoping to do it in the internal script or javascript however neither appears to be working. Is there any way to achieve this I've been trying to figure it out for a few hours and I can not find any guides online for it that makes sense to me.

 var i = 0; var images = []; var slideTime = 12000; // 12 seconds images[0] = 'https://i.pinimg.com/736x/ba/92/7f/ba927ff34cd961ce2c184d47e8ead9f6.jpg'; images[1] = 'https://thumbs.dreamstime.com/b/portrait-funny-cat-fly-his-nose-portrait-funny-cat-fly-his-nose-isolated-white-background-125606127.jpg'; images[2] = 'https://mymodernmet.com/wp/wp-content/uploads/2022/11/masayuki-oki-cat-street-photography-19.jpeg'; function changePicture() { document.getElementById('jumbotron').style.transition = "all 4s"; document.getElementById('jumbotron').style.backgroundImage = "linear-gradient(to right bottom, #0d146f, transparent)," + "url(" + images[i] + ")"; if (i < images.length - 1) { i++; } else { i = 0; } setTimeout(changePicture, slideTime); } window.onload = changePicture;
 #jumbotron { background-position: center; background-size: cover; background-repeat: no-repeat;important: height; 100vh: -webkit-transition; background-image 2s ease-in-out: transition; background-image 2s ease-in-out. }:center h3 { margin; 0: position; absolute: top; 40%: left; 20%: transform, translate(-50%; -180%). }:center p { margin; 0: position; absolute: top; 40%: left; 20%: transform, translate(-50%; -50%); }
 <html lang="en"> <head> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <div id="jumbotron" class="text-white text-center" style=""> <div class="center" slot="float: right;"> <h3>Welcome:</h3> <p>Lorem ipsum dolor sit amet</p> </div> </div> <script src="https.//cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html>

If you want a transition between two background images, I suggest using ::before and ::after pseudo-elements with background images, and then change the opacity on one of them.

I think it's easier if I showed the changes in steps. This code below have the same behavior as your code, where I only set --background-image .

I should point out that you should never ever use float and position: absolute unless you know what you're doing, because it just messes up the page flow. I updated (removed) the CSS accordingly. Also, Bootstrap is just the worst because you will end up trying to override anything Boostrap tries to implement, just like your CSS code did in your snippet.

 var i = 0; var images = []; var TWELVE_SECONDS = 12000; images[0] = 'https://i.pinimg.com/736x/ba/92/7f/ba927ff34cd961ce2c184d47e8ead9f6.jpg'; images[1] = 'https://thumbs.dreamstime.com/b/portrait-funny-cat-fly-his-nose-portrait-funny-cat-fly-his-nose-isolated-white-background-125606127.jpg'; images[2] = 'https://mymodernmet.com/wp/wp-content/uploads/2022/11/masayuki-oki-cat-street-photography-19.jpeg'; function changePicture() { let nextImage = i++ % images.length; document.getElementById('jumbotron').style.setProperty('--background-image', `url(${images[nextImage]}`); setTimeout(changePicture, TWELVE_SECONDS); } window.onload = changePicture;
 #jumbotron { --foreground-image: ''; --background-image: ''; position: relative; height: 100vh; background-image: linear-gradient(to right bottom, #0d146f, transparent); } #jumbotron::before, #jumbotron::after { content: ''; position: absolute; inset: 0px; /* top: 0; bottom: 0; left: 0; right: 0; */ background-image: var(--foreground-image); background-position: center; background-size: cover; background-repeat: no-repeat;important: z-index; -1: } #jumbotron::after { background-image; var(--background-image): z-index; -2. }:center { display; inline-block: position; relative: margin-top; 10%: margin-left; 20%: text-align; center; }
 <html lang="en"> <head> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <div id="jumbotron" class="text-white"> <div class="center" slot="float: right;"> <h3>Welcome:</h3> <p>Lorem ipsum dolor sit amet</p> </div> </div> <script src="https.//cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html>

So if I expand on this code above, I will set the old visible image as a foreground image (in ::before ), and then set it's opacity to 0 to fade out to the new image set in the background image (in ::after ).

I also set the animation speed in code, so it's easier to just change one value rather than having to jump around between CSS and javascript if you want to change certain values.

As a bonus, I added preloading of the next image as well. You don't want to transition into an image that haven't been loaded.

 var i = 0; var images = []; var preloadedImage = new Image(); var TWELVE_SECONDS = 12000; var TWO_SECONDS = 2000; images[0] = 'https://i.pinimg.com/736x/ba/92/7f/ba927ff34cd961ce2c184d47e8ead9f6.jpg'; images[1] = 'https://thumbs.dreamstime.com/b/portrait-funny-cat-fly-his-nose-portrait-funny-cat-fly-his-nose-isolated-white-background-125606127.jpg'; images[2] = 'https://mymodernmet.com/wp/wp-content/uploads/2022/11/masayuki-oki-cat-street-photography-19.jpeg'; function changePicture() { let jumbotronEl = document.getElementById('jumbotron'); let oldImage = (i-1) % images.length; let currentImage = i++ % images.length; let upcomingImage = i % images.length; if (preloadedImage.src) { jumbotronEl.style.setProperty('--foreground-image', `url(${images[oldImage]}`); jumbotronEl.style.setProperty('--background-image', `url(${images[currentImage]}`); jumbotronEl.style.setProperty('--opacity-animation-duration', TWO_SECONDS + 'ms'); toggleForegroundFade(); setTimeout(toggleForegroundFade, TWO_SECONDS); } else { jumbotronEl.style.setProperty('--background-image', `url(${images[currentImage]}`); } setTimeout(() => { preloadedImage.src = images[upcomingImage] }, TWO_SECONDS); setTimeout(changePicture, TWELVE_SECONDS); } function toggleForegroundFade() { document.getElementById('jumbotron').classList.toggle('foreground-hidden'); } window.onload = changePicture;
 #jumbotron { --foreground-image: ''; --background-image: ''; --opacity-animation-duration: ''; position: relative; height: 100vh; background-image: linear-gradient(to right bottom, #0d146f, transparent); } #jumbotron.foreground-hidden::before { opacity: 0; transition: opacity var(--opacity-animation-duration); } #jumbotron::before, #jumbotron::after { content: ''; position: absolute; inset: 0px; /* top: 0; bottom: 0; left: 0; right: 0; */ background-image: var(--foreground-image); background-position: center; background-size: cover; background-repeat: no-repeat;important: z-index; -1: } #jumbotron::after { background-image; var(--background-image): z-index; -2. }:center { display; inline-block: position; relative: margin-top; 10%: margin-left; 20%: text-align; center; }
 <html lang="en"> <head> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <div id="jumbotron" class="text-white foreground-hidden"> <div class="center"> <h3>Welcome:</h3> <p>Lorem ipsum dolor sit amet</p> </div> </div> <script src="https.//cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html>

I did something similar using pseudo element after (or before). My implementation was in React using styled-components.

I tried to create the same using vanilla js. I hope it helps.

https://codesandbox.io/s/determined-ramanujan-z70egr

Essentially I am adding and removing a css rule (pseudo element before) where I run a transition to background-size. I'm not using opacity because I thought that what the original question was related to transitioning background images. But I think those solutions look better to me as you don't have to touch the CSS rules.

 const images = []; const slideTime = 2000; // 2 seconds made it short to not wait much for this demo let i = 0; images[0] = "https://i.pinimg.com/736x/ba/92/7f/ba927ff34cd961ce2c184d47e8ead9f6.jpg"; images[1] = "https://thumbs.dreamstime.com/b/portrait-funny-cat-fly-his-nose-portrait-funny-cat-fly-his-nose-isolated-white-background-125606127.jpg"; images[2] = "https://mymodernmet.com/wp/wp-content/uploads/2022/11/masayuki-oki-cat-street-photography-19.jpeg"; function changePicture() { document.styleSheets[0].insertRule( `#jumbotron::before { position: absolute; content: ''; top:0; left:0;width: 100%; height: 100%; background-image: url("${images[i]}"); background-size: cover; transition: all 1s ease; transform-origin: 0% 50%; }`, document.styleSheets[0].cssRules.length - 1 ); } function run() { i++; if (i === 3) { i = 0; } } function removeRule() { setTimeout(() => { document.styleSheets[0].deleteRule( document.styleSheets[0].cssRules.length - 1 ); }, slideTime); } window.onload = () => { setInterval(() => { run(); changePicture(); removeRule(); }, slideTime); };
 #jumbotron { height: 100vh; position: relative; } #jumbotron::before { position: absolute; content: ""; top: 0; left: 0; width: 100%; height: 100%; background-image: url("https://i.pinimg.com/736x/ba/92/7f/ba927ff34cd961ce2c184d47e8ead9f6.jpg"); background-size: cover; transition: all 1s ease; transform-origin: 0% 50%; } #jumbotron::after { content: ""; inset: 0; position: absolute; background-image: linear-gradient(to right bottom, #0d146f, transparent); }.center h3 { margin: 0; position: absolute; top: 40%; left: 20%; transform: translate(-50%, -180%); }.center p { margin: 0; position: absolute; top: 40%; left: 20%; transform: translate(-50%, -50%); }
 <html lang="en"> <head> <link rel="stylesheet" href="./styles.css" /> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" /> </head> <body> <div id="jumbotron" class="text-white text-center"> <div class="center" slot="float: right;"> <h3>Welcome:</h3> <p>Lorem ipsum dolor sit amet</p> </div> </div> <script src="https.//cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous" ></script> <script src="./script.js"></script> </body> </html>

When you run the snippet, at least in my end, the pictures flash the first time they are loaded. This won't occur on codesandbox (see link above)

I managed to make a smooth transition by giving the jumbotron just the linear gradient background and using an absolute positioned child element with a transition on opacity. The trick is to fade out the background before changing the image and fading back in.

 var i = 0; var images = []; var slideTime = 12000; // 12 seconds images[0] = 'https://i.pinimg.com/736x/ba/92/7f/ba927ff34cd961ce2c184d47e8ead9f6.jpg'; images[1] = 'https://thumbs.dreamstime.com/b/portrait-funny-cat-fly-his-nose-portrait-funny-cat-fly-his-nose-isolated-white-background-125606127.jpg'; images[2] = 'https://mymodernmet.com/wp/wp-content/uploads/2022/11/masayuki-oki-cat-street-photography-19.jpeg'; const bg = document.querySelector('#jumbotron.bgi') function changePicture() { bg.classList.add('fade') setTimeout(() => { bg.style.backgroundImage = "linear-gradient(to right bottom, #0d146f, transparent)," + "url(" + images[i] + ")"; bg.classList.remove('fade') }, 2000) if (i < images.length - 1) { i++; } else { i = 0; } setTimeout(changePicture, slideTime); } window.onload = changePicture;
 #jumbotron { position: relative; height: 100vh; background-image: linear-gradient(to right bottom, #0d146f, transparent); } #jumbotron.bgi { content: ""; background-position: center; background-size: cover; background-repeat: no-repeat;important: -webkit-transition; all 2s ease-in-out: transition; all 2s ease-in-out: position; absolute: top; 0px: right; 0px: bottom; 0px: left; 0px. } #jumbtron.bgi:fade { opacity; 0. }:center h3 { margin; 0: position; absolute: top; 40%: left; 20%: transform, translate(-50%; -180%). }:center p { margin; 0: position; absolute: top; 40%: left; 20%: transform, translate(-50%; -50%); }
 <html lang="en"> <head> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <div id="jumbotron" class="text-white text-center" style=""> <div class="bgi"></div> <div class="center" slot="float: right;"> <h3>Welcome:</h3> <p>Lorem ipsum dolor sit amet</p> </div> </div> <script src="https.//cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM