Reactjs 如何模糊滚动上的背景图像?

标签 reactjs scroll blur styled-components

我是 reactjs 的新手,我想了解如何在 Reactjs 样式组件中重现这个 jquery 示例:模糊事件“滚动”上的背景图像 https://jsfiddle.net/BinaryMoon/8jhw2/

$(document).ready(function() {
    $(window).scroll(function(e) {
        var s = $(window).scrollTop(),
            opacityVal = (s / 200);

        $('.blurred-image').css('opacity', opacityVal);
    });
});
.img-src { 
    position: absolute;
    background:url(http://bromleydemo.files.wordpress.com/2013/10/blossom.jpg?w=600) center center;
    background-size: cover;
}

如您所见,后台 url 设置为 css prop 我在 reactjs 中尝试过一些东西,但每次滚动时,图像背景都会重新加载。 有人可以帮我吗?

ps : 如果这个解决方案可以用 styled-components 来实现,那就太棒了

ps2 : 这是我正在尝试实现的效果的另一页 https://codepen.io/zrichard/pen/wEFBd

谢谢

最佳答案

您的示例代码非常好,除了一件很难用所有这些框架正确实现的事情:滚动。

如果你打开一个调试控制台,你会看到这种警告信息(当你上下滚动时,如果你快速滚动,显示将是“空白”)

Over 200 classes were generated for component bg-opacity-v2__ImgSrc. Consider using the attrs method, together with a style object for frequently changed styles.

Example:
  const Component = styled.div.attrs({
    style: ({ background }) => ({
      background,
    }),
  })`width: 100%;`

  <Component />

我找到了一个使用组件“.attrs”方法的解决方案。

const ImgSrc = styled.div.attrs(props => ({
  style: {
    opacity: `${props.opacity}`,
    filter: "blur(" + `${props.filter}` + "px) brightness(0.7)",
  },
}))`
  position: absolute;
  background: url("http://bromleydemo.files.wordpress.com/2013/10/blossom.jpg?w=600")
    center center;
  background-size: cover;
  top: -10%;
  bottom: 10%;
  left: -10%;
  right: 10%;
  width: 120%;
  height: 120%;
`

这是您的代码的新版本。我删除了第一个标签,修改了不透明度计算,但这是一个细节。 我真的不明白为什么我必须从“useEffect”方法中提取不透明度计算,但它工作得很好。

const onScroll = () => {
    setOpacity(scrollOpacity())
    setFilter(scrollFilter())
}

这个新版本运行良好。

Live Sandbox

import React, { useState, useEffect } from "react";
import styled, { css } from "styled-components";
import { hydrate, render } from "react-dom";

function scrollOpacity() {
  const winScroll =
    document.body.scrollTop || document.documentElement.scrollTop;

  const height =
    document.documentElement.scrollHeight -
    document.documentElement.clientHeight;

  const scrolled = winScroll / height;
  const newOpacity = 1 + scrolled * 2;
  return newOpacity;
}

function scrollFilter() {
  const winScroll =
    document.body.scrollTop || document.documentElement.scrollTop;

  const newFilter = 0 + winScroll / 100;
  return newFilter;
}

function App() {
  const [opacity, setOpacity] = useState(1);
  const [filter, setFilter] = useState(0);

  useEffect(() => {
    const onScroll = () => {
      setOpacity(scrollOpacity());
      setFilter(scrollFilter());
    };

    window.addEventListener("scroll", onScroll);

    return function cleanup() {
      window.removeEventListener("scroll", onScroll);
    };
  }, []);

  return (
    <React.Fragment>
      <BlurredImageContainer>
        <ImgSrc opacity={opacity} filter={filter} />
      </BlurredImageContainer>
      <Content>
        <Avatar src="https://pbs.twimg.com/profile_images/378800000748837969/bd8e553e5cae83ef488c6b15166bdd55.png" />
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
        <p>This is some test content</p>
      </Content>
    </React.Fragment>
  );
}

const BlurredImageContainer = styled.div`
  display: block;
  padding: 0;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: -1;
`;

const ImgSrc = styled.div.attrs(props => ({
  style: {
    opacity: `${props.opacity}`,
    filter: "blur(" + `${props.filter}` + "px) brightness(0.7)"
  }
}))`
  position: absolute;
  background: url("http://bromleydemo.files.wordpress.com/2013/10/blossom.jpg?w=600")
    center center;
  background-size: cover;
  top: -10%;
  bottom: 10%;
  left: -10%;
  right: 10%;
  width: 120%;
  height: 120%;
`;

const Content = styled.div`
  padding: 150px 50px;
  color: #fff;
  text-align: center;
`;

const Avatar = styled.div`
  height: 120px;
  width: 120px;
  border-radius: 100%;
  border: 5px solid #fff;
  margin: 0 auto 50px;
`;

const rootElement = document.getElementById("root");
if (rootElement.hasChildNodes()) {
  hydrate(<App />, rootElement);
} else {
  render(<App />, rootElement);
}

如果有人有优化或更好的方法来做到这一点,欢迎您。

关于Reactjs 如何模糊滚动上的背景图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58972547/

相关文章:

javascript - 如何解析从后端到下拉列表的结果 React axios?

reactjs - 如何修复 React Native 中的 Firebase/firestore 错误?

firefox - Firefox:滚动包含嵌入YouTube视频的iframe

iOS 模糊效果到 ImageView 与 Swift

javascript - 与在 useEffect 中分配转发的 ref 相比,useImperativeHandle 有什么好处?

reactjs - 由于 : FIRESTORE (9. 6.1) 内部断言失败,无法编写 firestore 测试:意外状态

javascript - 没有滚动条的水平菜单滚动

javascript - 修复了使用按钮滚动到下一个 div 的问题

css - 默认模糊图像,悬停时显示?

image - 如何使用 ImageMagick 模糊/像素化图像的一部分,从而产生大像素?