【问题标题】:Radial animated focus effect with mask-image in React TSReact TS 中带有蒙版图像的径向动画焦点效果
【发布时间】:2022-08-18 18:21:15
【问题描述】:

我正在使用 mask-image 重新创建此径向动画焦点效果:Codepen 我知道我可以将 CSS 复制并粘贴到 .css 文件中,但我想使用样式组件来实现相同的结果。为此,我在样式化组件中声明了 CSS 并应用它。但我不确定为什么什么都没有发生。

应用程序.tsx

import React from \"react\";
import styled from \"styled-components\";

const Property = styled.div`
  @property --focal-size {
    syntax: \"<length-percentage>\";
    initial-value: 100%;
    inherits: false;
  }
`;

const FocusZoom = styled.div`
--mouse-x: center;
  --mouse-y: center;
  --backdrop-color: hsl(200 50% 0% / 50%); /* can\'t be opaque */
  --backdrop-blur-strength: 10px;
  
  position: fixed;
  touch-action: none;
  inset: 0;
  background-color: var(--backdrop-color);
  backdrop-filter: blur(var(--backdrop-blur-strength));
  
  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y), 
    transparent var(--focal-size), 
    black 0%
  );
  
  transition: --focal-size .3s ease;
  
  /*  debug/grok the gradient mask image here   */
/*   background-image: radial-gradient(
    circle, 
    transparent 100px, 
    black 0%
  ); */
}
`;

function App(bool: boolean) {
  const zoom: Element = document.querySelector(\"focus-zoom\");

  const toggleSpotlight = (bool) =>
    zoom.style.setProperty(\"--focal-size\", bool ? \"15vmax\" : \"100%\");

  window.addEventListener(\"pointermove\", (e) => {
    zoom.style.setProperty(\"--mouse-x\", e.clientX + \"px\");
    zoom.style.setProperty(\"--mouse-y\", e.clientY + \"px\");
  });

  window.addEventListener(\"keydown\", (e) => toggleSpotlight(e.altKey));
  window.addEventListener(\"keyup\", (e) => toggleSpotlight(e.altKey));
  window.addEventListener(\"touchstart\", (e) => toggleSpotlight(true));
  window.addEventListener(\"touchend\", (e) => toggleSpotlight(false));

  return (
    <>
      <h1>
        Press <kbd>Opt/Alt</kbd> or touch for a spotlight effect
      </h1>
      <FocusZoom></FocusZoom>
    </>
  );
}

export default App;

    标签: javascript css reactjs typescript styled-components


    【解决方案1】:

    查看带有样式组件的解决方案 Code sandbox

    import React, { useEffect } from "react";
    import styled, { createGlobalStyle } from "styled-components";
    
    export const GlobalStyle = createGlobalStyle`
      body {
        display: flex;
        align-items: center;
        justify-content: center;
      }
    
    /* custom properties */
      :root {  
        --focal-size: { 
        syntax: "<length-percentage>";
        initial-value: 100%;
        inherits: false;
      }
      --mouse-x: center;
      --mouse-y: center;
      --backdrop-color: hsl(200 50% 0% / 50%);
      --backdrop-blur-strength: 10px;
    }
    `;
    
    const Wrapper = styled.div`
      height: 400px;
      width: 400px;
      background: conic-gradient(
        from -0.5turn at bottom right,
        deeppink,
        cyan,
        rebeccapurple
      );
    `;
    const FocusZoom = styled.div`
      position: fixed;
      touch-action: none;
      inset: 0;
      background-color: var(--backdrop-color);
      backdrop-filter: blur(var(--backdrop-blur-strength));
    
      mask-image: radial-gradient(
        circle at var(--mouse-x) var(--mouse-y),
        transparent var(--focal-size),
        black 0%
      );
    
      transition: --focal-size 0.3s ease;
    `;
    
    function App(bool) {
      useEffect(() => {
        const zoom = document.getElementById("zoomId");
    
        const toggleSpotlight = (bool) =>
          zoom.style.setProperty("--focal-size", bool ? "15vmax" : "100%");
    
        window.addEventListener("pointermove", (e) => {
          zoom.style.setProperty("--mouse-x", e.clientX + "px");
          zoom.style.setProperty("--mouse-y", e.clientY + "px");
        });
    
        window.addEventListener("keydown", (e) => toggleSpotlight(e.altKey));
        window.addEventListener("keyup", (e) => toggleSpotlight(e.altKey));
        window.addEventListener("touchstart", (e) => toggleSpotlight(true));
        window.addEventListener("touchend", (e) => toggleSpotlight(false));
        toggleSpotlight();
      }, []);
    
      return (
        <Wrapper>
          <h1>
            Press <kbd>Opt/Alt</kbd> or touch for a spotlight effect
          </h1>
    
          <FocusZoom id="zoomId"></FocusZoom>
        </Wrapper>
      );
    }
    
    export default App;
    
    
    

    此外,请确保您在应用程序文件中导入了全局样式和组件。

    import Test, { GlobalStyle } from "./test";
    
    export default function App() {
      return (
        <div className="App">
          <GlobalStyle />
          <Test />
        </div>
      );
    }
    
    

    【讨论】:

    • 谢谢,我使用 Typescript,但出现了一些错误,尤其是“对象可能是‘空’”?
    • 你在哪里看到打字稿错误?这是打字稿版本codesandbox.io/s/…@Figario
    • 您正在将手动 DOM 操作与 React 混合使用。这不是好的做法。您不应该使用 getElementById、innerHTML 等。而是使用 React 的 DOM 操作方法
    • 那么我应该使用什么来代替 getElementById 呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 2022-10-25
    相关资源
    最近更新 更多