如何在 React 中创建 glassmorphism 效果(玻璃模糊效果)

1,286 阅读7分钟

Glassmorphism是一种很酷的UI设计趋势,它允许你在你的应用作品中创造出一种惊人的玻璃幻觉。它还可以提供一种冰霜般的效果,感觉就像一个模糊的或漂浮的图像。这在你的用户界面中创造了一个视觉层次,使你能够将注意力吸引到你打算强调的内容上。

下面是一个具有玻璃形态效果的投资组合网站标题的例子。

Example of glassmorphism on a portfolio website

图片来源

Glassmorphism是通过为定位在设定的背景之上的对象创造半透明背景的对比来实现的。

本指南将讨论glassmorphism的概念,并逐步说明如何在React应用程序中实现这种效果。我们将实现一个简单的待办事项应用程序,并在表单和每个任务卡上使用玻璃形态效果。

前提条件

为了理解这篇文章,你应该具备以下条件。

  • 拥有React的工作知识
  • Material UI的工作知识
  • 在你的电脑上安装了Node.js

使用Create React App设置一个React应用程序

Create React App是React团队提供的一个工具,它允许你在React中启动一个单页应用程序。

导航到你选择的项目目录,使用TypeScript和以下命令初始化React应用程序。

npx creat-react-app react-glassmorphism-app --template typescript

然后进入新创建的React应用目录。

cd react-glassmorphism-app

并启动React开发服务器,检查引导的模板是否在工作。

npm run start 

在你的默认浏览器上,boilerplate React页面将被加载到[http://localhost:3000/](http://localhost:3000/) ,以表明一切都在有序进行。

实现待办事项表单

为了创建一个新的任务,我们需要设置一个表单,让用户添加任务的细节,然后将其添加到待办事项列表中。导航到src/App.tsx ,实现一个待办事项表单,如下图所示。

在顶部导入App.css 。我们将使用这个文件来添加CSS类,以便为待办事项表单和任务卡设置样式。

import './App.css';

编辑渲染函数,添加一个带有titledescription 字段的表单,如下所示。

<div className="todos-container">
    <form className="form">
        <div className="form-group">
            <label htmlFor="title">Title</label>
            <input type="text" id="title" placeholder="Enter todo's title" name="title" required />
        </div>
        <div className="form-group">
            <label htmlFor="description">Description</label>
            <textarea id="description" placeholder="Describe the todo" name="description" required />
        </div>
        <div className="form-group">
            <button type="submit" class="form-submit-btn">
                Add todo
            </button>
        </div>
    </form>
</div>

这将创建一个todos-container ,其中有一个简单的表格。该表单将有用于添加任务标题的字段title ,用于添加任务描述的字段description ,以及用于提交细节的按钮submit

下一步是对这个表单进行样式设计。导航到src/App.css 文件并添加以下样式。

todos-container 类设置样式。

.todos-container{
    /* Entire page width */
    width:100%;
    /* Entire page height */
    height:100vh;
    /* Responsive layout */
    display:flex;
    /* Display on top of the other */
    flex-direction: column; 
    /* Display horizontally at the center */ 
    align-items: center;
    /* Smooth transition to bottom right with different colors */
    background-image: linear-gradient(to bottom right, #fc0345,#fc03b1,#4a03fc);
    /* To cover the entire screen */
    background-size:cover;
    /* Image position */
    background-position:center;
    /* To not repeat the image beyond it's scale */
    background-repeat:no-repeat;
}

form 类设置样式。

.form{
    /** Sizeable width for the form **/
    width:400px;
    /** Sizeable height for the form **/
    height:300px;
    /** Black color with opacity **/
    background-color:rgba(0,0,0,0.5);
    /** Responsive layout **/
    display:flex;
    /** One element on top of the other **/
    flex-direction:column;
    /** Vertically at the center **/
    justify-content: center;
    /** Smooth corners **/
    border-radius:10px;
    /** Top, bottom, right, and left spacing between form and it's content **/
    padding:20px;
    /** Spacing from the top **/
    margin-top:10px;
}

form-group 类设置样式。

.form-group{
    /** Bottom space between one form-group and the other **/
    margin-bottom:20px;
    /** Responsive layout **/
    display: flex;
    /** One element on top of the other **/
    flex-direction: column;
}

label 样式。

.form-group label{
    /** Medium font size **/
    font-size:16px;
    /** Visible color **/
    color:white;
    /** Bottom space between it and the input form **/
    margin-bottom:5px;
}

为表单输入设置样式。

.form-group input[type="text"],textarea{
    /** Size-able width of the input **/
    width:90%; 
    /** Size-able height of the input **/
    height:40px; 
    /** Smooth corners on all edges **/
    border-radius:5px;
    /** No line sorrounding the input **/ 
    border:none;
    /** Top, right, bottom, right spacing to where content starts **/
    padding:10px;
    /** Medium font **/
    font-size:16px;
    /** Visible color **/
    color:white;
    /** Dark background with some opacity **/
    background-color:rgba(0,0,0,0.5); 
}

submit 表单按钮设计样式。

.form-group .form-submit-btn{
    /** Take up the entire available width **/
    width:100%; 
    /** Sizeable height **/
    height:40px; 
    /** Smooth corners at all edges **/
    border-radius:5px;
    /** No line on the outline **/
    border:none;
    /** Greyish color **/
    background-color:rgba(255,255,255,0.5);
    /** Color of text **/
    color:black;
    /** Medium sized font **/
    font-size:16px
    /** Display a pointer when mouse is over it **/
    cursor:pointer;
}

在React应用程序中添加一个玻璃形态的效果

为了给我们的表单添加玻璃形态的效果,我们将给我们的.form 类添加以下样式。

一个线性梯度作为背景图片。

/** Smooth transition to the bottom from a greyish to a less greyish color **/
background-image:linear-gradient(to bottom right, rgba(255,255,255,0.2), rgba(255,255,255,0));

一个背景滤镜。

/** A blur effect behind the form **/
backdrop-filter: "blur(10px)"; 

一个盒状阴影。

/** Thick box shadow with a greyish background on the right, bottom, with a blurred shadow **/
box-shadow: 10px 10px 10px rgba(30,30,30,0.5);

添加完这些样式后,刷新你之前打开的[http://localhost:3000/](http://localhost:3000/) 标签。表单应该应用下面的玻璃形态效果。

Form with glassmorphism effect

使表格具有响应性

为了使表单具有响应性,我们将获得用户的输入并将其存储在我们组件的一个状态中。导航到src/App.tsx 文件并执行以下操作。

react 中导入useState 钩子。

import {useState} from 'react';

为待办事项定义一个接口。一个接口将描述待办事项列表中每个任务的结构。

interface Todo {
    title: string;
    description: string;
}

定义状态。

// our saved todos starting with an empty string
const [todos, setTodos] = useState([] as Todo[]); 
// title of a todo starting as an empty string
const [title, setTitle] = useState('' as string); 
// description of a todo starting as an empty string
const [description, setDescription] = useState('' as string); 

为标题字段添加一个onChange 事件。该事件将获得用户的输入并将其保存在当前标题的状态上。同时,将标题的值设置为状态上的当前标题。

<input type="text" onChange={e => setTitle(e.target.value)} id="title" placeholder="Enter todo's title" name="title" value={title} required/>

为描述字段添加一个onChange 事件。该事件将获得用户的输入并将其保存在当前描述的状态上。同时,将description的值设置为当前状态下的描述。

<textarea id="description" onChange={e => setDescription(e.target.value) } placeholder="Describe the todo" name="description" value={description} required />

构建一个函数来处理表单提交事件。

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    // Prevent executing the default form submission event
    e.preventDefault();
    // Structure our todo from the current state
    const todo = {
    title,
    description,
    };
    // Add the todo to the state
    setTodos([...todos, todo]);
    // Clean the title state
    setTitle('');
    // Clean the description state
    setDescription('');
}; 

最后,将该函数连接到表单上。

<form className="form" onSubmit={handleSubmit}>

显示一个具有玻璃形态效果的任务卡

保存任务后,我们需要向用户展示它们。我们将检查我们的状态是否有保存的任务。如果有,我们就通过它们进行映射。如果没有,我们就显示一个信息,说我们没有保存的任务。

在表单之后,我们将添加一个条件来检查我们是否有保存的任务。如果任务已经被保存,我们就循环浏览它们。

{
    todos.length > 0 ? (
        <ul className="todos-list">
        {
          todos.map((todo, index) => (
            <li key={index} className="todo-item">
              <h3>{todo.title}</h3>
              <p>{todo.description}</p>
            </li>
          ))            
        }
      </ul>
    ) : (
        <p className="no-todos">No todos yet</p>
    )
}

起初,你会看到文本No todos``yet 。然而,如果你填写表格并提交,你将能够看到你的任务。你还应该注意,当你刷新页面时,你不会看到你先前保存的任务,因为它们被存储在状态上。

让我们给no-todos 类添加一些样式,使其更加明显。导航到src/App.css 文件并实现以下样式。

.no-todos{
    /** White text color **/
    color:white
    /** Medium font **/
    font-size: 20px;
    /** Bold style **/
    font-weight: bold;
}

要为todos-list 类设置样式。

.todos-list{
    /** Top and bottom outer spacing of 10px and centered **/
    margin: 10px auto;
    /** No inner spacing **/
    padding:0px; 
    /** No list style **/
    list-style:none;
    /** Half of the parent's width **/
    width: 50%;  
}

todo-item 类设计样式。

.todo-item{
    /** Black with opacity **/
    background-color:rgba(0,0,0,0.5);
    /** Smooth transition from a greyish to a less greyish color **/
    background-image:linear-gradient(to bottom right, rgba(255,255,255,0.2), rgba(255,255,255,0)); 
    /* A blur effect behind the card */
    backdrop-filter: "blur(10px)"; 
    /** A think greyish shadow for the card to the right, bottom with a blurred shadow **/
    box-shadow: 10px 10px 10px rgba(30,30,30,0.5);
    /** Inner spacing between elements **/
    padding: 10px; 
    /** Smooth corners on all edges **/
    border-radius:20px;
    /** Bottom spacing **/
    margin-bottom:10px; 
}

确保你的开发服务器仍在运行,你的页面应该类似于这个图片。

To-do form and task cards with glassmorphism effect

结论

一般的glassmorphism想法是在一个物体上有一个半透明的模糊,给人一种磨砂玻璃的感觉。它主要使用backdrop-filter ,以这些模糊的属性。其他的CSS属性,如颜色、边框半径、边框和阴影,可以根据你的应用偏好进行修改。玻璃形态效果可以补充独立的设计组件,如内容卡、导航栏和侧边栏。

我希望你觉得这篇文章对你有帮助!