首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于背景颜色滚动时更改SVG填充

基于背景颜色滚动时更改SVG填充
EN

Stack Overflow用户
提问于 2021-05-25 03:15:56
回答 1查看 190关注 0票数 0

我正在建立一个React网站,其中有section面板滑动使用position: sticky滚动,但有问题的fixed元素和他们的color适当的section background-color

下面是这个问题的一个简单片段。

代码语言:javascript
运行
复制
html {
  font-family: sans-serif;
  font-size: 20px;
  font-weight: 700;
  text-transform: uppercase;
}

*,
 ::after,
 ::before {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow-x: hidden;
}

.nav {
  position: fixed;
  width: 100;
  top: 0;
  left: 0;
  right: 0;
  padding: 24px 28px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

svg {
  fill: black; // Change to white over dark backgrounds
}

.sticky {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: sticky;
  top: -1px;
}

.dark {
  background-color: #1e1e1e;
  color: #fff;
}
代码语言:javascript
运行
复制
<div class="nav"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="32px" id="Layer_1" style="enable-background:new 0 0 32 32;" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve"><path d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z M28,14H4c-1.104,0-2,0.896-2,2  s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2  S29.104,22,28,22z"/></svg></div>
<main>
  <div class="sticky">Section Light</div>
  <div class="sticky dark">Section Dark</div>
</main>

我见过其他例子,当覆盖的元素定位为absolute时,它们在这种情况下不起作用,因为每个section面板都使用sticky位置。此外,使用mix-blend-mode是不可能的,因为某些部分使用了背景图像,这看起来很糟糕。

其次,网站是用GatsbyReact构建的,我可以访问每个版块的背景色。

如何在滚动不同的背景颜色时更改menu svg的颜色?我只想要白色或黑色的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-25 15:52:36

我们可以使用intersectionObserver告诉我们,当新的部分位于视口顶部附近时,并相应地更改菜单图标的颜色。相反,当一个部分出现在靠近顶部的位置时,根据它的前一个兄弟元素(即下面的元素)的黑色状态来更改菜单。

这段代码演示了以下内容:

代码语言:javascript
运行
复制
const svg = document.querySelector('svg');
let callback = (entries, observer) => {
  entries.forEach(entry => {
  //List from MDN:
    // Each entry describes an intersection change for one observed
    // target element:
    //   entry.boundingClientRect
    //   entry.intersectionRatio
    //   entry.intersectionRect
    //   entry.isIntersecting
    //   entry.rootBounds
    //   entry.target
    //   entry.time
    //eventually make the gradient chosen depend on the % overlap and the color of the previous sibling element
    if (entry.isIntersecting) {
      svg.style.fill = (entry.target.classList.contains('dark')) ? 'url(#white)' : 'url(#black)';
    }
    else {
      svg.style.fill = (entry.target.previousElementSibling.classList.contains('dark')) ? 'url(#white)' : 'url(#black)';
    }
  });
};
let options = {
  threshold: [ 0.9, 0.94, 0.98 ] // need to work on these thresholds
}

let observer = new IntersectionObserver(callback, options);
const stickies = document.querySelectorAll('main div.sticky');
stickies.forEach( sticky => {
  observer.observe(sticky);
});
代码语言:javascript
运行
复制
html {
  font-family: sans-serif;
  font-size: 20px;
  font-weight: 700;
  text-transform: uppercase;
}

*,
 ::after,
 ::before {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow-x: hidden;
}

.nav {
  position: fixed;
  width: 100;
  top: 0;
  left: 0;
  right: 0;
  rpadding: 24px 28px;
  padding: 2vh 28px;
  rpadding: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  z-index: 999;
}

svg {
  fill: black;
}

.sticky {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: sticky;
  top: -1px;
  background-color: white;
}

.dark {
  background-color: #1e1e1e;
  color: #fff;
}
代码语言:javascript
运行
复制
<div class="nav">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="32px" id="Layer_1" style="enable-background:new 0 0 32 32;" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve">
  <defs>
    <linearGradient id="black" x1="0%" y1="0%" x2="100%" y2="0%"  gradientTransform="rotate(90)">
      <stop offset="0%"   stop-color="#000"/>
      <stop offset="100%" stop-color="#000"/>
    </linearGradient>
    <linearGradient id="white" x1="0%" y1="0%" x2="100%" y2="0%"  gradientTransform="rotate(90)">
      <stop offset="0%"   stop-color="#fff"/>
      <stop offset="100%" stop-color="#fff"/>
    </linearGradient>
  </defs>
    <path d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z M28,14H4c-1.104,0-2,0.896-2,2  s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2  S29.104,22,28,22z"/>
    </svg>
</div>
<main>
  <div class="sticky">Section 1 Light</div>
  <div class="sticky dark">Section 2 Dark</div>
  <div class="sticky">Section 3 Light</div>
  <div class="sticky">Section 4 Light</div>
  <div class="sticky">Section 5 Light</div>
  <div class="sticky dark">Section 6 Dark</div>
</main>

为了让菜单图标栏随着部分的上下变化,我们可以感知重叠的比率,并使用适当的线性渐变设置svg填充颜色-具有第三个、第二个和完全完整的线性渐变。上面的代码片段设置了阈值,并开始使用线性渐变,但它并不完整-需要进行更多的计算才能使%s正确。我希望在某个时候有时间回到这个问题上来。

请注意,为了在具有不同纵横比的视口上进行观察,导航的顶部填充已更改为相对值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67677758

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档