如何从左到右滚动背景颜色动画

时间:2017-06-23 08:19:56

标签: javascript jquery html css

这是我的代码

      <div class="titlediv" style='background:linear-gradient(90deg, #cc2900 79%, #b3b3b3 21%);'>
        <h2> Hii
        </div>
        
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        <p> My name is Josh and I need Help </p>
        
      <div class="titlediv" style='background:linear-gradient(90deg, #cc2900 79%, #b3b3b3 21%);'>
        <h2> Hii
        </div>

如您所见,有2个<h2>标签带有背景颜色。

我想在屏幕上显示背景颜色从左到右填充。

就像这个网站:http://html.wwwebinvader.com/MovieMe/MovieMe-Light/index.html

向下滚动并查看IMDB评级等。

1 个答案:

答案 0 :(得分:1)

跟踪当前视口内的元素

基本上,您需要聆听window上的scroll event,并使用.offsetTop检查您的标题元素(h2)是否在视口内offsetHeight

动画CSS渐变

关于渐变动画,linear-gradient are not animatable

解决方案是将初始渐变作为元素的background,然后使用另一个元素(或pseudo-element)在另一个元素的顶部堆叠另一个渐变,并使用正确的{{1 }}然后使用其他可设置动画的属性来伪造渐变动画。

通常,您将使用z-index从一个渐变过渡到另一个渐变(第一个示例)或opacitypositionlefttop。 ..逐步填充渐变(第二个例子)。

两个渐变之间的示例转换

width
// Get all the heading elements:

const titles = document.querySelectorAll('.title');
const total = titles.length;

let windowHeight = window.innerHeight;

// Track the current heading, as you don't need to recheck those that have already been shown once:

let current = 0;

function onScroll() {
  // Get the bottom scroll position:
  
  const bottomScrollY = window.scrollY + windowHeight;
  
  // Check each heading that has not been shown yet:
  
  for (let i = current; i < total; ++i) {
    const title = titles[i];
    
    // Check that the heading is completely visible (all of it inside the current viewport):
    
    if (bottomScrollY > title.offsetTop + title.offsetHeight) {  
      // Add it the .active class:
      
      title.classList.add('active');
      
      // Skip this heading the next time:
      
      ++current;
      
      // If all headings are already active, remove the listeners:
  
      if (current === total) {
        window.removeEventListener('scroll', onScroll);
        window.removeEventListener('resize', onResize);
      }
    }
  }
}

function onResize() {
  // Update windowHeight:
  
  windowHeight = window.innerHeight;
}

// Initialize for the first time:

onScroll();

// Start listening for scroll and resize events:

window.addEventListener('scroll', onScroll);
window.addEventListener('resize', onResize);
body {
  margin: 0;
  font-family: sans-serif;
}

.title {
  position: relative;
  margin: 0;
  padding: 1rem;
  color: #000;
  background: linear-gradient(to right, #F00 0%, #FF0 100%);
  z-index: 1;
}

.title::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  opacity: 0;
  background: linear-gradient(to right, #00F 0%, #0FF 100%);
  transition: opacity ease-in .25s;
}

.active::before {
  opacity: 1;
}

逐步填充渐变的示例

<h2 class="title">TITLE 1</h2>

<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>

<h2 class="title">TITLE 2</h2>

<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>

<h2 class="title">TITLE 3</h2>

<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>

<h2 class="title">TITLE 4</h2>

<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
        
<h2 class="title">TITLE 5</h2>

<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
<p>...</p>
// Get all the heading elements:

const titles = document.querySelectorAll('.title');
const total = titles.length;

let windowHeight = window.innerHeight;

// Track the current heading, as you don't need to recheck those that have already been shown once:

let current = 0;

function onScroll() {
  // Get the bottom scroll position:
  
  const bottomScrollY = window.scrollY + windowHeight;
  
  // Check each heading that has not been shown yet:
  
  for (let i = current; i < total; ++i) {
    const title = titles[i];
    
    // Check that the heading is completely visible (all of it inside the current viewport):
    
    if (bottomScrollY > title.offsetTop + title.offsetHeight) {  
      // Add it the .active class:
      
      title.classList.add('active');
      
      // Skip this heading the next time:
      
      ++current;
      
      // If all headings are already active, remove the listeners:
  
      if (current === total) {
        window.removeEventListener('scroll', onScroll);
        window.removeEventListener('resize', onResize);
      }
    }
  }
}

function onResize() {
  // Update windowHeight:
  
  windowHeight = window.innerHeight;
}

// Initialize for the first time:

onScroll();

// Start listening for scroll and resize events:

window.addEventListener('scroll', onScroll);
window.addEventListener('resize', onResize);
body {
  margin: 0;
  font-family: sans-serif;
}

.title {
  position: relative;
  margin: 0;
  padding: 1rem;
  color: #000;
  z-index: 1;
  opacity: 0;
  transition: opacity ease-in .25s;
}

.title::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  z-index: -1;
  background: linear-gradient(to right, #FF0 0%, #FFF 100%);
  transition: width ease-in .25s;
}

.active {
  opacity: 1;
}

.active::before {
  width: 100%;
}