svg在不同部分的流体颜色变化

时间:2017-06-15 08:58:19

标签: javascript css svg

我正在尝试根据当前剖面背景更改SVG的颜色...它使用形状但是只要我将其更改为路径它就会跳转颜色而不是流体变化...为什么是那?

这就是我想要实现的目标(颜色的流畅过渡)

var sections = document.querySelectorAll('section');
var logo = document.querySelector('#logo');
var nextColor = document.querySelector('#nextColor');
var currentColor = document.querySelector('#currentColor');
var initialHeight = logo.clientHeight;
var lastScrollPosition = 0;

// Set current section color
sections.forEach(function (section) {
  var top = section.offsetTop - window.pageYOffset;
  if (top <= logo.offsetTop && (top + section.clientHeight) >= logo.offsetTop) {
    currentColor.setAttribute('fill', section.dataset.color);
  }
});

window.addEventListener('scroll', function () {
  sections.forEach(function (section) {
    var top = section.offsetTop - window.pageYOffset;
    var offset = top - logo.offsetTop;
    
    // If the top edge of the section is behind the logo
    if (top <= logo.offsetTop) {
      // Make sure the section color has its initial height
      currentColor.setAttribute('height', initialHeight);
      // If the logo is still inside the section, fill it with the section color
      var bottom = top + section.clientHeight;
      if (bottom >= logo.offsetTop) {
        currentColor.setAttribute('fill', section.dataset.color);
      }
      
      return;
    }
    
    // If logo collides with the lower section
    if (offset <= logo.clientHeight) {
      nextColor.setAttribute('fill', section.dataset.color);
      currentColor.setAttribute('height', offset);
    }
  });
});
#logo {
  position: fixed;
  position: fixed;
  top: 50%;
  left: 50%;
  margin-top: -50px;
  margin-left: -50px;
}

section {
  height: 100vh
}

#dark {
  background-color: #2a2a2a;
}
<div id="logo">
  <svg height="100" width="100">
    <rect id="nextColor" width="100" height="100"/>
    <rect id="currentColor" y="0" width="100" height="100"/>
  </svg>
</div>

<div class="sections">
  <section data-color="#000000" id="light"></section>
  <section data-color="#ffffff" id="dark"></section>
  <section data-color="#cccccc" id="light2"></section>
</div>

这就是我得到的,但它没有像上面的工作示例那样顺利过渡:

var sections = document.querySelectorAll('section');
var logo = document.querySelector('#logo');
var nextColor = document.querySelector('#nextColor');
var currentColor = document.querySelector('#currentColor');
var initialHeight = logo.clientHeight;
var lastScrollPosition = 0;

// Set current section color
sections.forEach(function (section) {
  var top = section.offsetTop - window.pageYOffset;
  if (top <= logo.offsetTop && (top + section.clientHeight) >= logo.offsetTop) {
    currentColor.setAttribute('fill', section.dataset.color);
  }
});

window.addEventListener('scroll', function () {
  sections.forEach(function (section) {
    var top = section.offsetTop - window.pageYOffset;
    var offset = top - logo.offsetTop;
    
    // If the top edge of the section is behind the logo
    if (top <= logo.offsetTop) {
      // Make sure the section color has its initial height
      currentColor.setAttribute('height', initialHeight);
      // If the logo is still inside the section, fill it with the section color
      var bottom = top + section.clientHeight;
      if (bottom >= logo.offsetTop) {
        currentColor.setAttribute('fill', section.dataset.color);
      }
      
      return;
    }
    
    // If logo collides with the lower section
    if (offset <= logo.clientHeight) {
      nextColor.setAttribute('fill', section.dataset.color);
      currentColor.setAttribute('height', offset);
    }
  });
});
#logo {
  position: fixed;
  position: fixed;
  top: 50%;
  left: 50%;
  margin-top: -50px;
  margin-left: -50px;
}

section {
  height: 100vh
}

#blue {
  background-color: #b4da55;
}
<div id="logo">

  <svg height="48" xmlns="http://www.w3.org/2000/svg">
    
    <path height="48" id="nextColor" d="M5.8 0v36.3h10.7V48l25.6-11.7V0H5.8zm10.5"/>
    
    <path height="48" id="currentColor" y="0" d="M5.8 0v36.3h10.7V48l25.6-11.7V0H5.8zm10.5"/>
 
  </svg>
</div>

<div class="sections">
  <section data-color="#b4da55" id="white"></section>
  <section data-color="#ffffff" id="blue"></section>
  <section data-color="#b4da55" id="white"></section>
</div>

2 个答案:

答案 0 :(得分:2)

您的代码没有像我认为的那样使用SVG矩形。为了证明这一点,我将rect更改为ellipse s,然后根据需要更改了属性,即ycywidth到{{ 1}}和rxheight。结果表明,首先,形状只显示整个形状的一部分(右下四分之一?),其次,当截面边界覆盖时,实际上挤压形状。你在原始例子中看不到这些东西,因为矩形的四分之一仍然是一个矩形,而一个压扁的矩形仍然是一个矩形。因此,您认为在原始示例中工作的内容实际上并不起作用。所以问题不是使用路径,而是原始代码。

如果您只想使用矩形,我可以按原样使用原始代码,因为 会产生所需的视觉效果。但是,如果您只使用矩形作为概念验证并且您的真正最终目标是使用路径,那么您需要一种不同的方法。您可以考虑使用ry / clipPath来&#34; cut&#34;作为区域边界的部分路径正在通过它,但这将需要对代码进行一些重要的重新处理。

&#13;
&#13;
clip-path
&#13;
var sections = document.querySelectorAll('section');
var logo = document.querySelector('#logo');
var nextColor = document.querySelector('#nextColor');
var currentColor = document.querySelector('#currentColor');
var initialHeight = logo.clientHeight;
var lastScrollPosition = 0;

// Set current section color
sections.forEach(function (section) {
  var top = section.offsetTop - window.pageYOffset;
  if (top <= logo.offsetTop && (top + section.clientHeight) >= logo.offsetTop) {
    currentColor.setAttribute('fill', section.dataset.color);
  }
});

window.addEventListener('scroll', function () {
  sections.forEach(function (section) {
    var top = section.offsetTop - window.pageYOffset;
    var offset = top - logo.offsetTop;
    
    // If the top edge of the section is behind the logo
    if (top <= logo.offsetTop) {
      // Make sure the section color has its initial height
      currentColor.setAttribute('ry', initialHeight);
      // If the logo is still inside the section, fill it with the section color
      var bottom = top + section.clientHeight;
      if (bottom >= logo.offsetTop) {
        currentColor.setAttribute('fill', section.dataset.color);
      }
      
      return;
    }
    
    // If logo collides with the lower section
    if (offset <= logo.clientHeight) {
      nextColor.setAttribute('fill', section.dataset.color);
      currentColor.setAttribute('ry', offset);
    }
  });
});
&#13;
#logo {
  position: fixed;
  position: fixed;
  top: 50%;
  left: 50%;
  margin-top: -50px;
  margin-left: -50px;
}

section {
  height: 100vh
}

#dark {
  background-color: #2a2a2a;
}
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这可以通过clipping矩形内的白色徽标来实现。

逻辑如下:

  • 始终显示绿色徽标
  • 每当“蓝色”部分与徽标重叠时,移动一个矩形以覆盖重叠的表面(更改它的位置和高度)
  • 白色徽标被裁剪在此矩形内,并显示在绿色徽标的顶部

更新了以下内容。如果发生的事情并不完全清楚,您可以将rect定义移到clipPath之外,这样您就可以看到它的位置和可见性如何随着滚动而变化。

附注:您可能希望debounce滚动事件侦听器,以在页面中保持良好的性能。

var logo = document.querySelector('#logo')
    , clipRect = document.querySelector('#clipRect')
    , blueSection = document.querySelector('#blue')

window.addEventListener('scroll', function () {

    // position of the top of the blue section
    var top = blueSection.offsetTop - window.pageYOffset
        // position of the bottom of the blue section
        , bottom = blueSection.offsetTop + blueSection.clientHeight - window.pageYOffset
    
    // offset between top of the logo and top of the blue section
    var offset = top - logo.offsetTop


    if ( offset <= logo.clientHeight && bottom >= logo.offsetTop) {
    // blue section overlaps with the logo

        clipRect.setAttribute('y', Math.max(offset, 0))
        
        clipRect.setAttribute('height', bottom - logo.offsetTop)
    }
    else {
    // blue section does not overlap with the logo
    
        // make sure the clip-path isn't visible
        clipRect.setAttribute('y', 0)
        clipRect.setAttribute('height', 0)
    }
    
})
#logo {
  position: fixed;
  position: fixed;
  top: 50%;
  left: 50%;
  margin-top: -50px;
  margin-left: -50px;
}

section {
  height: 100vh
}

#blue {
  background-color: #b4da55;
}

#currentColor {
  fill: #b4da55;
}

#nextColor {
  fill: white;
}

/*
following useful only for testing purpose
*/
#clipRect {
  fill: red;
  fill-opacity: .5;
}
<div id="logo">

  <svg height="48" xmlns="http://www.w3.org/2000/svg">
	<defs>
		<clipPath id="clipping">
		  <rect id="clipRect" x="0" y="0" width="48" height="0"></rect>
		</clipPath>
	</defs>
    
    <path height="48" id="currentColor" d="M5.8 0v36.3h10.7V48l25.6-11.7V0H5.8zm10.5"/>
    <path height="48" id="nextColor" d="M5.8 0v36.3h10.7V48l25.6-11.7V0H5.8zm10.5" clip-path="url(#clipping)"/>

     
  </svg>
</div>

<div class="sections">
  <section data-color="#b4da55" id="white"></section>
  <section data-color="#ffffff" id="blue"></section>
  <section data-color="#b4da55" id="white"></section>
</div>