如何为带动态边框的容器实现类灯泡发光光晕效果?
问题描述
我有一个带有动态移动边框的容器,目前该功能运行正常。最后一步需要为其实现类似灯泡的发光光晕效果(效果为跟随动态亮段的柔和扩散黄色光晕)。截至目前,我已尝试设置颜色、模糊及亮度效果,但未达到预期效果,不确定如何叠加多层效果,希望能得到帮助。
以下是我目前的代码:
import React, { useState } from 'react'; import styled, { createGlobalStyle, keyframes } from 'styled-components'; const GlobalStyle = createGlobalStyle` *, *::before, *::after { box-sizing: border-box; } body { display: grid; place-content: center; gap: 2rem; min-height: 100vh; background-image: conic-gradient( at 125% 50%, #b78cf7, #ff7c94, #ffcf0d, #ff7c94, #b78cf7 ); font-family: system-ui; } `; const continuousDashOffsetAnimation = keyframes` from { stroke-dashoffset: 0; } to { stroke-dashoffset: -50px; } `; const Box = styled.div` cursor: pointer; font-size: 2rem; font-family: inherit; font-weight: 700; color: hsl(320, 40%, 40%); background-color: hsl(349 100% 95%); width: 510px; height: 100px; border: 0; border-radius: 1.25rem; display: flex; align-items: center; justify-content: center; --glow-line-color: #FFD600; --glow-line-thickness: 2px; --glow-line-length: ${props => (props.speed > 15 ? "30px" : "10px")}; --glow-blur-color: #FFD600; --glow-blur-size: 5px; --glow-offset: 0px; --animation-speed: ${props => (props.speed > 15 ? "500ms" : "1500ms")}; --container-offset: 100px; --intense-glow-size: 15px; position: relative; .glow-container { pointer-events: none; position: absolute; inset: calc(var(--container-offset) / -2); width: calc(100% + var(--container-offset)); height: calc(100% + var(--container-offset)); opacity: 1; } .glow-blur, .glow-line { width: calc(100% - var(--container-offset) + var(--glow-offset)); height: calc(100% - var(--container-offset) + var(--glow-offset)); x: calc((var(--container-offset) / 2) + calc(var(--glow-offset) / -2)); y: calc((var(--container-offset) / 2) + calc(var(--glow-offset) / -2)); fill: transparent; stroke: black; stroke-width: 5px; stroke-dasharray: var(--glow-line-length) calc(50px - var(--glow-line-length)); animation: ${continuousDashOffsetAnimation} var(--animation-speed) linear infinite; } .glow-line { stroke: var(--glow-line-color); stroke-width: var(--glow-line-thickness); } .glow-blur { filter: blur(var(--glow-blur-size)) brightness(5.5); stroke: var(--glow-blur-color); stroke-width: var(--glow-blur-size); } &:after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; border-radius: inherit; background: radial-gradient(ellipse at center, rgba(255,214,0,0.6) 0%, transparent 70%); filter: blur(var(--intense-glow-size)); z-index: -1; } `; const App = () => { const [speed, setSpeed] = useState(10); // Initially set to 10 as an example return ( <> <GlobalStyle /> <Box speed={speed}> Hi there 👋 <svg className="glow-container"> <rect rx="1.25rem" pathLength="100" strokeLinecap="round" className="glow-blur"></rect> <rect rx="1.25rem" pathLength="100" strokeLinecap="round" className="glow-line"></rect> </svg> <button onClick={() => setSpeed(prevSpeed => (prevSpeed > 15 ? 10 : 20))}> Toggle Speed </button> </Box> </> ); } export default App;
解决方案
要实现类似灯泡的分层发光效果,核心是通过多层SVG描边叠加不同强度的模糊和亮度,同时配合容器背景的径向渐变光晕。以下是修改后的完整代码:
import React, { useState } from 'react'; import styled, { createGlobalStyle, keyframes } from 'styled-components'; const GlobalStyle = createGlobalStyle` *, *::before, *::after { box-sizing: border-box; } body { display: grid; place-content: center; gap: 2rem; min-height: 100vh; background-image: conic-gradient( at 125% 50%, #b78cf7, #ff7c94, #ffcf0d, #ff7c94, #b78cf7 ); font-family: system-ui; } `; const continuousDashOffsetAnimation = keyframes` from { stroke-dashoffset: 0; } to { stroke-dashoffset: -50px; } `; const Box = styled.div` cursor: pointer; font-size: 2rem; font-family: inherit; font-weight: 700; color: hsl(320, 40%, 40%); background-color: hsl(349 100% 95%); width: 510px; height: 100px; border: 0; border-radius: 1.25rem; display: flex; align-items: center; justify-content: center; --glow-line-color: #FFD600; --glow-line-thickness: 2px; --glow-line-length: ${props => (props.speed > 15 ? "30px" : "10px")}; --glow-blur-color: #FFD600; --glow-blur-size: 8px; --glow-intense-blur: 15px; --glow-offset: 0px; --animation-speed: ${props => (props.speed > 15 ? "500ms" : "1500ms")}; --container-offset: 100px; --intense-glow-size: 20px; position: relative; .glow-container { pointer-events: none; position: absolute; inset: calc(var(--container-offset) / -2); width: calc(100% + var(--container-offset)); height: calc(100% + var(--container-offset)); opacity: 1; } .glow-blur, .glow-line, .glow-intense { width: calc(100% - var(--container-offset) + var(--glow-offset)); height: calc(100% - var(--container-offset) + var(--glow-offset)); x: calc((var(--container-offset) / 2) + calc(var(--glow-offset) / -2)); y: calc((var(--container-offset) / 2) + calc(var(--glow-offset) / -2)); fill: transparent; stroke-dasharray: var(--glow-line-length) calc(50px - var(--glow-line-length)); animation: ${continuousDashOffsetAnimation} var(--animation-speed) linear infinite; strokeLinecap: round; } .glow-line { stroke: var(--glow-line-color); stroke-width: var(--glow-line-thickness); opacity: 0.9; } .glow-blur { filter: blur(var(--glow-blur-size)) brightness(3); stroke: var(--glow-blur-color); stroke-width: var(--glow-blur-size); opacity: 0.7; } .glow-intense { filter: blur(var(--glow-intense-blur)) brightness(4); stroke: var(--glow-blur-color); stroke-width: var(--glow-intense-blur); opacity: 0.5; } &:after { content: ''; position: absolute; top: -5px; left: -5px; right: -5px; bottom: -5px; border-radius: inherit; background: radial-gradient(ellipse at center, rgba(255,214,0,0.3) 0%, transparent 60%); filter: blur(var(--intense-glow-size)); z-index: -1; opacity: 0.6; } `; const App = () => { const [speed, setSpeed] = useState(10); return ( <> <GlobalStyle /> <Box speed={speed}> Hi there 👋 <svg className="glow-container"> <rect rx="1.25rem" className="glow-intense"></rect> <rect rx="1.25rem" className="glow-blur"></rect> <rect rx="1.25rem" className="glow-line"></rect> </svg> <button onClick={() => setSpeed(prevSpeed => (prevSpeed > 15 ? 10 : 20))}> Toggle Speed </button> </Box> </> ); } export default App;
关键改动说明
- 新增
--glow-intense-blur变量,专门控制强光晕的模糊半径,实现灯泡发光的层次感 - 在SVG中添加第三层
rect(.glow-intense),作为最外层的强发光效果,通过更大的模糊和更高的亮度模拟光晕扩散感 - 调整
.glow-blur的参数,降低亮度并增大模糊,让基础光晕更柔和,避免和强光晕冲突 - 修改
:after伪元素的径向渐变范围和透明度,扩大伪元素尺寸让光晕更自然,同时降低整体透明度避免刺眼 - 调整各层描边的透明度,通过多层叠加实现渐变式发光,更接近灯泡发光的真实质感
内容的提问来源于stack exchange,提问作者Angel Hadzhiev
相关产品推荐
相关产品推荐

