绘制H5页面时,模糊效果(或称为毛玻璃效果)被广泛用于增强用户界面的美观性和层次感。这种效果不仅可以吸引用户的注意,还能提供视觉上的分隔,而不完全阻挡背后的内容。基于此,本文封装一个React组件,该组件能够在容器上实现层次化的模糊效果,使得开发者可以轻松地在其项目中应用并自定义这种设计风格。
先放效果图:
需求分析
该组件需要满足以下几个基本需求:
- 可自定义模糊层数:组件应允许用户设置模糊效果的层数,以便于调整模糊效果的精度和深度。
- 可自定义模糊强度:用户应能够设置模糊的最大强度,以控制最外层的模糊程度。
- 可自定义容器尺寸和形状:包括容器的高度和边框圆角半径。
- 自定义类名:允许用户添加自定义类名,以便于在外部CSS文件中进一步样式定制。
构建过程
基于上述需求,我们设计了HcBlurBox
组件。下面是构建此组件的具体步骤:
1. 设置组件接收的Props
首先,我们定义组件能够接收的props,包括:
accuracy
(模糊层数)radius
(边框圆角半径)height
(容器高度)maxBlur
(最大模糊值)ratio
(高度比率)className
(自定义类名)
2. 计算模糊层样式
对于每一个模糊层,我们根据传入的accuracy
、maxBlur
和ratio
来动态计算其高度和模糊度。使用Array(accuracy).fill(0).map
来创建指定数量的模糊层,并为每层应用以下样式规则:
- 高度(
height
):根据ratio
和accuracy
计算得出的每层的高度百分比。 - 模糊效果(
backdropFilter
):使用CSS的blur()
函数,根据层的顺序和maxBlur
来动态计算模糊度。
3. 条件渲染
为了确保组件的灵活性和健壮性,我们在没有提供height
属性时让组件返回null
,以避免渲染不必要的DOM元素。
4. 应用样式和自定义类名
最后,我们将计算得到的样式应用到每个模糊层上,并通过${className}
模板字符串将用户提供的自定义类名添加到容器div
上,以实现进一步的样式自定义。
完整代码展示
javascript
import React from "react";
import "./index.less";
/**
* 创建一个具有层次模糊效果的容器组件。
*
* @component
* @param {Object} props - 组件接收的props。
* @param {number} [props.accuracy=2] - 精度,决定模糊层的数量。
* @param {number} [props.radius=5] - 模糊层的边框圆角半径。
* @param {number} props.height - 容器的高度,必须提供。
* @param {number} [props.maxBlur=12.5] - 最大模糊值。
* @param {number} [props.ratio=100] - 高度比率,用于计算每个模糊层的高度百分比。
* @param {string} [props.className=''] - 容器的自定义类名。
* @returns {ReactElement|null} 返回一个模糊效果的React组件,如果没有提供高度,则返回null。
*
* @example
* <HcBlurBox height={100} accuracy={3} maxBlur={15} className="custom-class" />
*/
const HcBlurBox = (props) => {
const {
accuracy = 2,
radius = 5,
height,
maxBlur = 12.5,
ratio = 100,
className = '',
} = props;
// 如果没有提供高度,则不渲染组件
if(!height) return null;
return (
<div className={`hc-blur-box-container ${className}`}>
{Array(accuracy).fill(0).map(
(v, i) => {
const step = i + 1;
const _height = ratio - (100 / accuracy) * i; // 计算每个模糊层的高度百分比
const blur = `blur(${(maxBlur / accuracy) * step}px)`; // 根据精度和步骤计算模糊效果
// 如果计算得到的高度小于2倍的height,则不渲染该层
if (2 * radius > _height * height / 100) return null;
return (
<div
key={i} // 添加key以满足React列表渲染的要求
className="hc-blur-box"
style={{
height: `${_height}%`, // 设置模糊层的高度
backdropFilter: blur, // 应用模糊效果
borderBottomLeftRadius: radius, // 设置边框圆角半径
borderBottomRightRadius: radius,
}}
/>
)
}
)}
</div>
)
}
export default HcBlurBox;
less
.hc-blur-box-container {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
.hc-blur-box {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
backdrop-filter: blur(2.5px);
mask: linear-gradient(to top, rgb(0, 0, 0) 50%, rgba(0, 0, 0, 0.8) 70%, rgba(0, 0, 0, 0) 100%);
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.64) 100%);
z-index: 1;
border: none ;
}
}
通过HcBlurBox
组件,开发者可以轻松在其React项目中实现具有层次模糊效果的容器,大大丰富了界面的视觉效果和用户体验。此组件的灵活性和可定制性,使其能够适应各种设计需求。
兼容方案
上述代码虽然能够完成最终效果,但是有的浏览器不支持mask css属性,这个时候,只需要通过绝对定位和父容器等大的div去模拟mask的效果就可以了。以下的代码是兼容组件,当然你喜欢的话可以将两个组件融合成一个。
兼容组件
jsx
import React from "react";
import "./index.less"; // 引入样式文件
const DoubleLayeredDiv = () => {
return (
<div className="container">
{[...Array(10).keys()].map((index) => (
<div
key={index}
className={`background-image img${index + 1}`}
style={{
background-position-y: -10*(index+1);
filter: `blur(${index+1}px)`;
bottom: -10*(index+1);
}}
></div>
))}
<div className="gradient-overlay"></div>
<div className="content">Your Content Here</div>
</div>
);
};
export default DoubleLayeredDiv;
对应的样式文件 (index.less
)
less
.container {
margin: auto;
margin-top: 200px;
position: relative;
width: 400px;
height: 600px;
overflow: hidden;
border-radius: 30px;
box-shadow: 0 0 20px 0px;
background-image: url('./page1.jpg');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.background-image {
width: 100%;
height: 600px;
background-image: url('./page1.jpg');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
position: absolute;
left: 0;
z-index: 1;
}
.gradient-overlay {
width: 100%;
height: 500px;
background-image: linear-gradient(to top, black, transparent);
position: absolute;
bottom: 0;
left: 0;
z-index: 2;
}
.content {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 3;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 20px;
}
兼容backdrop-filter
虽然现代浏览器普遍支持CSS的backdrop-filter
属性来实现模糊效果,但是并非所有浏览器都支持(特别是旧版浏览器)。对于不支持backdrop-filter
属性的浏览器,我们可以采取以下兼容性方案:
-
使用多层图片叠加 :如上述组件所示,通过创建多个带有不同模糊度的图层(使用
filter: blur()
),我们可以在不支持backdrop-filter
的环境下模拟出类似的视觉效果。 -
使用静态模糊背景图片 :为了进一步兼容那些连
filter
属性也不支持的古老浏览器,可以预先生成一张模糊的背景图片,并在需要时作为备选方案使用。 -
优雅降级:对于极端的兼容性需求,可以考虑在不支持模糊效果的浏览器中简单隐藏这些效果,保留基本的内容展示。这可以通过JavaScript检测特定CSS属性的支持情况来实现。
总之,虽然完全的跨浏览器兼容性往往难以实现,但通过巧妙地利用CSS和JavaScript,仍然可以为大多数用户提供接近设计意图的体验,同时为那些使用旧浏览器的用户提供可接受的备选方案。