问题
I'm trying to change the background image of an element after a certain position has been scrolled past. Here's a snippet of my code:
<body>
<script>
window.onscroll = function() {scrollBG()};
function scrollBG() {
if (document.body.scrollTop > document.getElementById("one").getBoundingClientRect().top ||
document.documentElement.scrollTop > document.getElementById("one").getBoundingClientRect().top) {
document.getElementById("outer").style.backgroundImage = "url('imgs/pic1.jng')";
} else {
document.getElementById("outer").style.backgroundImage = "url('imgs/pic2.jpg')";
}
}
</script>
<table id="outer">
I'm using a similar coding style to show/hide a "back to top" button after a certain scroll position that functions just fine. I don't think there's a conflict between the two (though inline scripting isn't my preferred style) because even when I remove everything related to the "back to top" button, my code still fails to function.
Is this a stupid syntactical error, or is there a more fundamental error to my approach?
回答1:
I've tweaked your code a little and it's working:
jsFiddle 1
var divOuter = document.getElementById("outer"),
divOne = document.getElementById("one");
window.onscroll = function() {scrollBG()};
function scrollBG() {
var oneTop = divOne.getBoundingClientRect().top;
if(document.body.scrollTop > oneTop ||
document.documentElement.scrollTop > oneTop){
divOuter.style.backgroundImage = "url('//www.planwallpaper.com/static/images/518071-background-hd_xO1TwRc.jpg')";
} else {
divOuter.style.backgroundImage = "url('//www.planwallpaper.com/static/images/maxresdefault_YodSsVN.jpg')";
}
}
body { margin: 0; padding: 0; height: 1500px; }
#outer {
position: fixed;
background: url('//www.planwallpaper.com/static/images/maxresdefault_YodSsVN.jpg') no-repeat;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#one {
width: 100%;
height: 150px;
background-color: orange;
color: white;
position: relative;
top: 400px;
}
<div id="outer"></div>
<div id="one"><h1>This is One</h1></div>
However, following the above method will be inefficient as IMHO it makes an extra HTTP request for the images every time the scroll goes up and down the threshold and thus you'll see flickering every time the background images get changed.
So it'd be better if we make use of an external CSS class, i.e #outer.bg2
, and just add/remove it depending on the position of the scroll and this will fetch a cached version of the image which makes it smooth [except for the first time when the image is being requested for the first time]. Like below:
jsFiddle 2
var divOuter = document.getElementById("outer"),
divOne = document.getElementById("one");
window.onscroll = function() { scrollBG() };
function scrollBG() {
var oneTop = divOne.offsetTop;
if (document.body.scrollTop > oneTop ||
document.documentElement.scrollTop > oneTop) {
divOuter.classList.add('bg2');
} else {
divOuter.classList.remove('bg2');
}
}
body{ margin:0; padding:0; height: 1500px; }
#outer{
position:fixed;
background: url('//www.planwallpaper.com/static/images/maxresdefault_YodSsVN.jpg') no-repeat;
top:0;
left:0;
right:0;
bottom:0;
}
#outer.bg2{
background: url('//www.planwallpaper.com/static/images/518071-background-hd_xO1TwRc.jpg');
}
#one{
width:100%;
height:150px;
background-color:orange;
color:white;
position:relative;
top:400px;
}
<div id="outer"></div>
<div id="one"><h1>This is One</h1></div>
In the above code the triggering will happen when the scroll meets the bottom of the element #one
, if you want the triggering to happen according to the top edge then replace this:
var oneTop = divOne.offsetTop;
With this:
var oneTop = divOne.offsetTop - divOne.offsetHeight;
jsFiddle 3
来源:https://stackoverflow.com/questions/44371552/changing-background-image-onscroll