【GLM-5 陪练式创意 UI 实战】第二篇:创意魔法盒 —— 从 “开心” 到 “科技感”,AI 驱动的 UI 风格迭代

目录

【GLM-5 陪练式创意 UI 实战】第二篇:创意魔法盒 —— 从 “开心” 到 “科技感”,AI 驱动的 UI 风格迭代

引  言

1 迭代背景与指令触发

1.1 迭代指令设计

1.2 GLM-5 参数适配

2 科技感风格的设计拆解(与 “开心版” 差异对比)

2.1 配色方案:从暖黄到霓虹

2.2 视觉特效:从呼吸到扫描

3 核心代码实现与差异解析

3.1 背景与特效实现

3.2 故障艺术与霓虹发光

3.3 交互与动画触发

4 本地效果验证:从 Flutter 到 HTML 的跨栈调试

4.1 项目创建与代码替换

4.2 效果验证要点

4.3 运行效果展示

5 实践感悟


活动仓库链接:https://atomgit.com/GitCode/0daymodel

GLM-5 模型体验链接:https://ai.atomgit.com/zai-org/GLM-5/model-inference?utm_source=tiezi

✨ 主题 3:创意魔法盒 —— 情绪驱动的动态 UI 生成器

引  言

        在第一篇博客中,我借助 GLM-5 完成了 “开心、明亮、活泼” 主题的 Flutter UI 构建,实现了情绪与视觉的初步融合。而 “情绪驱动 UI” 的核心魅力,在于风格随情绪迭代的灵活性。本篇中,我将触发指令 ——“现在我想换成科技感的风格”,重新让 GLM-5 完成从暖色调 “开心版” 到赛博朋克 “科技感版” 的 UI 重构,解锁 AI 辅助 UI 迭代的完整流程。

1 迭代背景与指令触发

1.1 迭代指令设计

基于主题 3 “情绪驱动 UI” 的核心要求,我向 GLM-5 触发了迭代指令:

现在我想换成科技感的风格。

同时,GLM-5 自动完成了需求分析,明确了 “科技感” 风格的关键特征:

  • 配色:深色背景(黑 / 深蓝 / 深灰)+ 霓虹点缀(青色、品红、电光蓝);
  • 排版:几何感无衬线字体(Orbitron/Rajdhani)+ 全大写标题;
  • 视觉:网格背景、故障艺术、扫描线、发光边框;
  • 动画:悬停霓虹脉冲、滚动触发的技能条填充。
用户想要将他们当前的网站风格切换为“科技感”风格。

**1. 分析需求:**
*   **目标:** 将现有网站设计转换为“科技感”风格。
*   **语境:** 我需要回顾之前的交互(虽然在这个无状态环境中我无法严格“记忆”,但我假设用户指的是一个标准的个人主页或作品集网站,或者我需要提供一个通用的模板)。既然用户说“换成”,这意味着存在一个之前的设计。我将假设一个标准的结构:导航栏、Hero区域、关于、技能、项目、联系方式。
*   **“科技感”风格的关键特征:**
    *   **配色方案:** 深色背景(黑色、深蓝、深灰),霓虹点缀(青色、品红、电光蓝、石灰绿)。
    *   **排版:** 单间距字体、几何无衬线字体、大号标题、全大写文本。
    *   **视觉效果:**
        *   渐变(线性或径向)。
        *   发光效果(盒阴影、文本阴影)。
        *   网格背景、粒子、线条、电路图案。
        *   玻璃拟态(半透明背景)。
    *   **动画:** 悬停时的故障效果、打字机效果、平滑滚动、霓虹灯发光脉冲。

**2. 设计策略(构思草稿):**

*   **背景:** 深色(`#0a0a0a` 或 `#0f172a`)。也许加一个微妙的网格覆盖。
*   **主色调:** 青色/电光蓝(`#00f2ea` 或 `#0ea5e9`)。
*   **辅助色:** 品红/紫色(`#ff0055` 或 `#a855f7`)。
*   **字体:** 'Orbitron'(经典科幻)或 'Roboto Mono'(代码感)。让我们使用 'Orbitron' 作为标题,'Rajdhani' 或 'Inter' 作为正文。
*   **组件:**
    *   *导航栏:* 玻璃拟态效果,底部发光边框。
    *   *Hero区域:* 大号故障文本,粒子背景(CSS或简单JS),打字机效果。
    *   *卡片:* 深色半透明背景,霓虹边框,悬停时的“扫描线”效果。
    *   *按钮:* 霓虹边框,悬停时填充发光。

**3. 实现细节(HTML/CSS/JS):**

*   **HTML结构:** 标准语义标签。
*   **CSS:**
    *   定义颜色的根变量。
    *   `font-family` 导入。
    *   *故障效果:* 使用 `text-shadow` 和 `clip-path` 的 CSS 动画。
    *   *霓虹发光:* `box-shadow`。
    *   *网格背景:* 使用 `linear-gradient` 的 CSS 图案。
*   **JS:** 用于打字机效果的简单脚本,也许还有一个基本的粒子系统(为了保持代码简洁,我将坚持使用纯CSS动画或非常简单的JS)。

**4. 起草代码(迭代优化):**

*   *配色方案:*
    *   背景:`#0d0d0d`(深黑)
    *   主要文本:`#e0e0e0`(浅灰)
    *   强调色 1:`#00f0ff`(青色)
    *   强调色 2:`#f000ff`(品红)

*   *Hero区域:*
    *   标题:“SYSTEM ONLINE”或类似内容。
    *   副标题:打字机效果。
    *   背景:一个微妙的网格。

*   *技能/项目:*
    *   带有“科技”边框的卡片(角落装饰)。

**5. 构建回复:**
*   确认需求。
*   提供完整的 HTML 文件(包含 CSS 和 JS),以便用户可以直接复制粘贴。
*   解释关键设计元素(颜色、字体、效果),以便用户理解这些变化。

**6. 优化代码(起草过程中的自我修正):**
*   *批评:* 纯黑可能太刺眼了。让我们使用非常深的蓝灰色 `#020617` (slate-950)。
*   *字体:* Google Fonts 'Orbitron' 是“科技感”的标志性字体。我必须包含它。
*   *动画:* “故障”效果很酷,但对于主标题来说可能太分散注意力。我会将其应用于悬停或特定的静态元素。
*   *背景:* CSS 网格图案比导入沉重的粒子 JS 库更轻量且更容易。
    *   `background-image: linear-gradient(rgba(0, 255, 255, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(0, 255, 255, 0.1) 1px, transparent 1px);`
    *   `background-size: 30px 30px;`

**7. 最终代码结构:**
*   `<!DOCTYPE html>`
*   `<head>`:Google Fonts 链接,内部 `<style>`。
*   `<body>`:
    *   导航栏(玻璃效果)。
    *   Hero(故障文本,打字机)。
    *   关于(科技风格文本)。
    *   技能(进度条或数据流风格)。
    *   项目(卡片带霓虹边框)。
    *   页脚。
    *   背景网格(固定位置)。
*   `<script>`:打字机逻辑,滚动显示。

**8. 撰写解释:**
*   强调“赛博朋克/科幻”美学。
*   提及具体的 CSS 技巧(用于故障的 `clip-path`,用于霓虹的 `box-shadow`)。

**(最终输出生成过程中的自我修正):**
确保代码是独立的。不要依赖外部图像;使用占位符或 CSS 形状。确保文本对比度高(深色背景上的霓虹色)。

让我们生成代码好的,为您将网站风格切换为**科技感**风格。

这种风格通常具有以下特点:
*   **配色**:深色背景(黑/深蓝/深灰)搭配高亮霓虹色(青色、品红、电光蓝)。
*   **字体**:使用几何感强、类似于编码或未来主义的字体(如 Orbitron)。
*   **视觉效果**:网格背景、发光效果、故障艺术、扫描线、玻璃拟态。

以下是为您重构的完整 HTML 代码:

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TECH SYSTEM | 个人主页</title>
    <!-- 引入科技感字体 Orbitron -->
    <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Rajdhani:wght@300;500;700&display=swap" rel="stylesheet">
    <style>
        /* --- 全局变量定义 --- */
        :root {
            --bg-color: #050505;
            --text-color: #e0e0e0;
            --primary-color: #00f3ff; /* 电光青 */
            --secondary-color: #bc13fe; /* 霓虹紫 */
            --accent-color: #2dff00; /* 终端绿 */
            --card-bg: rgba(20, 20, 30, 0.7);
            --border-glow: 0 0 10px var(--primary-color), inset 0 0 5px var(--primary-color);
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Rajdhani', sans-serif;
            background-color: var(--bg-color);
            color: var(--text-color);
            overflow-x: hidden;
            line-height: 1.6;
        }

        /* --- 背景网格效果 --- */
        .grid-bg {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-image: 
                linear-gradient(rgba(0, 243, 255, 0.05) 1px, transparent 1px),
                linear-gradient(90deg, rgba(0, 243, 255, 0.05) 1px, transparent 1px);
            background-size: 50px 50px;
            z-index: -1;
            pointer-events: none;
        }

        /* --- 扫描线动画 --- */
        .scanline {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 5px;
            background: rgba(0, 243, 255, 0.3);
            box-shadow: 0 0 15px var(--primary-color);
            z-index: 1000;
            pointer-events: none;
            animation: scan 4s linear infinite;
        }

        @keyframes scan {
            0% { top: -5%; }
            100% { top: 105%; }
        }

        /* --- 导航栏 --- */
        nav {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px 5%;
            background: rgba(5, 5, 5, 0.8);
            backdrop-filter: blur(10px);
            border-bottom: 1px solid rgba(0, 243, 255, 0.2);
            position: fixed;
            width: 100%;
            top: 0;
            z-index: 100;
        }

        .logo {
            font-family: 'Orbitron', sans-serif;
            font-weight: 900;
            font-size: 1.8rem;
            color: var(--primary-color);
            text-shadow: 0 0 10px var(--primary-color);
            letter-spacing: 2px;
        }

        .nav-links {
            list-style: none;
            display: flex;
            gap: 30px;
        }

        .nav-links a {
            text-decoration: none;
            color: var(--text-color);
            font-weight: 500;
            font-size: 1.1rem;
            text-transform: uppercase;
            letter-spacing: 1px;
            position: relative;
            padding: 5px 0;
        }

        .nav-links a::after {
            content: '';
            position: absolute;
            width: 0;
            height: 2px;
            bottom: 0;
            left: 0;
            background-color: var(--primary-color);
            box-shadow: 0 0 5px var(--primary-color);
            transition: width 0.3s;
        }

        .nav-links a:hover {
            color: var(--primary-color);
        }

        .nav-links a:hover::after {
            width: 100%;
        }

        /* --- Hero 区域 --- */
        .hero {
            height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
            position: relative;
        }

        .hero-title {
            font-family: 'Orbitron', sans-serif;
            font-size: 4rem;
            font-weight: 900;
            margin-bottom: 20px;
            text-transform: uppercase;
            position: relative;
            color: #fff;
        }

        /* 故障艺术效果 */
        .glitch {
            position: relative;
        }
        
        .glitch::before, .glitch::after {
            content: attr(data-text);
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }

        .glitch::before {
            left: 2px;
            text-shadow: -1px 0 var(--secondary-color);
            clip: rect(24px, 550px, 90px, 0);
            animation: glitch-anim 2s infinite linear alternate-reverse;
        }

        .glitch::after {
            left: -2px;
            text-shadow: -1px 0 var(--primary-color);
            clip: rect(85px, 550px, 140px, 0);
            animation: glitch-anim2 3s infinite linear alternate-reverse;
        }

        @keyframes glitch-anim {
            0% { clip: rect(30px, 9999px, 10px, 0); }
            20% { clip: rect(15px, 9999px, 100px, 0); }
            40% { clip: rect(50px, 9999px, 20px, 0); }
            60% { clip: rect(80px, 9999px, 120px, 0); }
            80% { clip: rect(10px, 9999px, 60px, 0); }
            100% { clip: rect(40px, 9999px, 90px, 0); }
        }

        @keyframes glitch-anim2 {
            0% { clip: rect(60px, 9999px, 10px, 0); }
            20% { clip: rect(100px, 9999px, 30px, 0); }
            40% { clip: rect(10px, 9999px, 80px, 0); }
            60% { clip: rect(30px, 9999px, 50px, 0); }
            80% { clip: rect(90px, 9999px, 10px, 0); }
            100% { clip: rect(20px, 9999px, 70px, 0); }
        }

        .hero-subtitle {
            font-size: 1.5rem;
            color: var(--primary-color);
            margin-bottom: 40px;
            letter-spacing: 3px;
            text-shadow: 0 0 5px rgba(0, 243, 255, 0.5);
        }

        .cta-btn {
            padding: 15px 40px;
            background: transparent;
            border: 2px solid var(--primary-color);
            color: var(--primary-color);
            font-family: 'Orbitron', sans-serif;
            font-weight: 700;
            text-transform: uppercase;
            cursor: pointer;
            position: relative;
            overflow: hidden;
            transition: color 0.3s, box-shadow 0.3s;
            text-decoration: none;
            display: inline-block;
        }

        .cta-btn:hover {
            color: #050505;
            background: var(--primary-color);
            box-shadow: 0 0 20px var(--primary-color), inset 0 0 20px rgba(255,255,255,0.2);
        }

        /* --- 通用区块样式 --- */
        .section {
            padding: 100px 10%;
        }

        .section-title {
            font-family: 'Orbitron', sans-serif;
            font-size: 2.5rem;
            color: var(--primary-color);
            margin-bottom: 50px;
            text-align: center;
            text-transform: uppercase;
            position: relative;
        }

        .section-title::after {
            content: '';
            display: block;
            width: 100px;
            height: 2px;
            background: var(--secondary-color);
            margin: 10px auto;
            box-shadow: 0 0 10px var(--secondary-color);
        }

        /* --- 技能区域 --- */
        .skills-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 30px;
        }

        .skill-card {
            background: var(--card-bg);
            border: 1px solid rgba(0, 243, 255, 0.1);
            padding: 30px;
            position: relative;
            transition: transform 0.3s, border-color 0.3s;
            clip-path: polygon(0 0, 100% 0, 100% 85%, 90% 100%, 0 100%); /* 切角效果 */
        }

        .skill-card:hover {
            transform: translateY(-5px);
            border-color: var(--primary-color);
            box-shadow: 0 0 15px rgba(0, 243, 255, 0.1);
        }

        .skill-card h3 {
            font-family: 'Orbitron', sans-serif;
            color: var(--primary-color);
            margin-bottom: 15px;
            font-size: 1.2rem;
        }

        .skill-bar {
            height: 5px;
            background: rgba(255, 255, 255, 0.1);
            margin-top: 10px;
            position: relative;
        }

        .skill-progress {
            height: 100%;
            background: var(--primary-color);
            box-shadow: 0 0 10px var(--primary-color);
            width: 0; /* 动画初始值 */
            transition: width 1.5s ease-in-out;
        }

        /* --- 项目区域 --- */
        .projects-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 30px;
        }

        .project-card {
            background: linear-gradient(135deg, rgba(20,20,30,0.9), rgba(10,10,15,0.9));
            border: 1px solid rgba(255, 255, 255, 0.05);
            overflow: hidden;
            position: relative;
            transition: 0.3s;
        }

        .project-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(0, 243, 255, 0.1), transparent);
            transition: 0.5s;
        }

        .project-card:hover::before {
            left: 100%;
        }

        .project-content {
            padding: 30px;
            border-top: 2px solid transparent;
            transition: border-color 0.3s;
        }

        .project-card:hover .project-content {
            border-top-color: var(--secondary-color);
        }

        .project-title {
            font-family: 'Orbitron', sans-serif;
            font-size: 1.3rem;
            margin-bottom: 15px;
            color: #fff;
        }

        .project-desc {
            font-size: 0.95rem;
            color: #aaa;
            margin-bottom: 20px;
        }

        .tag {
            display: inline-block;
            padding: 4px 8px;
            background: rgba(0, 243, 255, 0.1);
            color: var(--primary-color);
            font-size: 0.8rem;
            border: 1px solid rgba(0, 243, 255, 0.2);
            margin-right: 5px;
            margin-bottom: 5px;
        }

        /* --- 页脚 --- */
        footer {
            padding: 50px 5%;
            background: rgba(0, 0, 0, 0.8);
            text-align: center;
            border-top: 1px solid rgba(0, 243, 255, 0.1);
        }

        .footer-text {
            font-family: 'Orbitron', sans-serif;
            color: #555;
            font-size: 0.8rem;
            letter-spacing: 2px;
        }

        /* --- 响应式 --- */
        @media (max-width: 768px) {
            .hero-title {
                font-size: 2.5rem;
            }
            .nav-links {
                display: none; /* 移动端简化 */
            }
        }
    </style>
</head>
<body>

    <!-- 背景特效层 -->
    <div class="grid-bg"></div>
    <div class="scanline"></div>

    <!-- 导航栏 -->
    <nav>
        <div class="logo">PORTFOLIO.IO</div>
        <ul class="nav-links">
            <li><a href="#home">Home</a></li>
            <li><a href="#skills">Skills</a></li>
            <li><a href="#projects">Projects</a></li>
            <li><a href="#contact">Contact</a></li>
        </ul>
    </nav>

    <!-- Hero 区域 -->
    <section class="hero" id="home">
        <h1 class="hero-title glitch" data-text="FUTURE IS NOW">FUTURE IS NOW</h1>
        <p class="hero-subtitle">// FULL STACK DEVELOPER & UI DESIGNER //</p>
        <a href="#projects" class="cta-btn">Initialize System</a>
    </section>

    <!-- 技能区域 -->
    <section class="section" id="skills">
        <h2 class="section-title">System Modules</h2>
        <div class="skills-grid">
            <div class="skill-card">
                <h3>Frontend Architecture</h3>
                <p>React, Vue, Three.js 构建高性能交互界面。</p>
                <div class="skill-bar"><div class="skill-progress" data-width="90%"></div></div>
            </div>
            <div class="skill-card">
                <h3>Backend Logic</h3>
                <p>Node.js, Python, Go 数据处理与API设计。</p>
                <div class="skill-bar"><div class="skill-progress" data-width="85%"></div></div>
            </div>
            <div class="skill-card">
                <h3>UI/UX Design</h3>
                <p>Figma, After Effects 赛视觉与动效设计。</p>
                <div class="skill-bar"><div class="skill-progress" data-width="80%"></div></div>
            </div>
        </div>
    </section>

    <!-- 项目区域 -->
    <section class="section" id="projects">
        <h2 class="section-title">Data Logs</h2>
        <div class="projects-grid">
            <div class="project-card">
                <div class="project-content">
                    <h3 class="project-title">Project: Cyberpunk-Dash</h3>
                    <p class="project-desc">一个基于WebGL的数据可视化仪表盘,具有强烈的赛博朋克风格。</p>
                    <span class="tag">Three.js</span>
                    <span class="tag">React</span>
                    <span class="tag">WebGL</span>
                </div>
            </div>
            <div class="project-card">
                <div class="project-content">
                    <h3 class="project-title">Project: Neural-Net</h3>
                    <p class="project-desc">模拟神经网络运算过程的交互式教育网站。</p>
                    <span class="tag">Python</span>
                    <span class="tag">TensorFlow</span>
                </div>
            </div>
            <div class="project-card">
                <div class="project-content">
                    <h3 class="project-title">Project: E-Commerce</h3>
                    <p class="project-desc">高并发电商系统架构设计与实现。</p>
                    <span class="tag">Go</span>
                    <span class="tag">Microservices</span>
                </div>
            </div>
        </div>
    </section>

    <!-- 页脚 -->
    <footer id="contact">
        <p class="footer-text">SYSTEM STATUS: ONLINE // VERSION 2.0.1 // &copy; 2023 TECH PORTFOLIO</p>
    </footer>

    <script>
        // 简单的打字机效果逻辑可以在这里添加
        // 这里主要实现技能条动画的触发

        // 观察技能条进入视口
        const skillBars = document.querySelectorAll('.skill-progress');
        
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const width = entry.target.getAttribute('data-width');
                    entry.target.style.width = width;
                    observer.unobserve(entry.target);
                }
            });
        }, { threshold: 0.5 });

        skillBars.forEach(bar => {
            observer.observe(bar);
        });

        // 导航栏平滑滚动
        document.querySelectorAll('a[href^="#"]').forEach(anchor => {
            anchor.addEventListener('click', function (e) {
                e.preventDefault();
                document.querySelector(this.getAttribute('href')).scrollIntoView({
                    behavior: 'smooth'
                });
            });
        });
    </script>
</body>
</html>
```

### 主要修改点说明:

1.  **配色方案**:
    *   背景换成了极深的黑色 (`#050505`),模拟终端或太空背景。
    *   主色调换成了电光青 (`#00f3ff`) 和霓虹紫 (`#bc13fe`),这是赛博朋克/科技风格的经典配色。

2.  **背景特效**:
    *   添加了 `.grid-bg`:使用 CSS 线性渐变绘制了透视网格背景。
    *   添加了 `.scanline`:一条上下循环移动的扫描线,模拟老式CRT显示器或雷达扫描的效果。

3.  **字体选择**:
    *   标题使用了 **Orbitron**,这是一种非常有名的几何感、未来主义字体。
    *   正文使用了 **Rajdhani**,看起来像技术文档或HUD(平视显示器)文字。

4.  **视觉效果**:
    *   **故障艺术**:Hero 区域的大标题添加了 CSS `clip-path` 动画,模拟信号干扰的抖动效果。
    *   **切角卡片**:技能卡片使用了 `clip-path: polygon(...)` 切掉右下角,这是科幻UI设计中常见的形状。
    *   **发光边框**:按钮和卡片 hover 时都有明显的 `box-shadow` 发光效果。
    *   **标签样式**:项目中的标签看起来像代码编辑器中的关键字高亮。

您可以直接复制这段代码覆盖之前的文件,刷新浏览器即可看到充满未来科技感的新界面。

1.2 GLM-5 参数适配

为保证迭代代码的完整性与稳定性,延续了第一篇的参数设置:

  • Max Tokens:8192(避免长代码截断);
  • Temperature:0.2(聚焦风格需求,减少冗余输出);
  • 其他参数保持默认,确保 AI 精准落地 “科技感” 设计。

2 科技感风格的设计拆解(与 “开心版” 差异对比)

GLM-5 基于 “科技感” 关键词,生成了一套与 “开心版” 完全不同的设计方案,核心差异如下:

模块 开心版(Flutter) 科技感版(HTML/CSS/JS) 设计逻辑
配色方案 暖白背景 + 向日葵黄 / 珊瑚橙 深黑背景 + 电光青 / 霓虹紫 暖色调传递快乐,冷霓虹强化未来感
背景特效 呼吸圆形装饰 网格背景 + 扫描线动画 模拟终端 / 雷达扫描的科技氛围
字体选择 系统默认字体 Orbitron(标题)+ Rajdhani(正文) 几何感字体强化未来主义风格
核心动画 弹性入场 + 呼吸动画 故障艺术 + 霓虹发光 + 切角卡片 故障效果模拟信号干扰,切角卡片贴合科幻 UI
布局结构 响应式网格(移动端 2 列 / 桌面 4 列) 玻璃拟态导航 + 卡片式技能 / 项目区 玻璃效果提升科技感,卡片布局强化信息层级

2.1 配色方案:从暖黄到霓虹

科技感版采用  深黑背景(#050505)+ 电光青(#00f3ff)+ 霓虹紫(#bc13fe 的组合,既避免了纯黑的刺眼感,又通过霓虹色的发光效果,营造出赛博朋克的未来氛围。

2.2 视觉特效:从呼吸到扫描

  • 网格背景:通过 CSS 线性渐变绘制透视网格,模拟终端界面;
  • 扫描线动画:一条上下循环移动的青色扫描线,还原 CRT 显示器的扫描效果;
  • 故障艺术:Hero 标题通过clip-path动画实现抖动偏移,模拟信号干扰;
  • 切角卡片:技能卡片使用clip-path: polygon(...)切掉右下角,贴合科幻 UI 的几何造型。

3 核心代码实现与差异解析

GLM-5 生成的科技感 UI 为完整的 HTML/CSS/JS 代码,核心实现与 “开心版” Flutter 代码的差异如下:

3.1 背景与特效实现

/* 网格背景 */
.grid-bg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-image: 
    linear-gradient(rgba(0, 243, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 243, 255, 0.05) 1px, transparent 1px);
  background-size: 50px 50px;
  z-index: -1;
}

/* 扫描线动画 */
.scanline {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 5px;
  background: rgba(0, 243, 255, 0.3);
  box-shadow: 0 0 15px var(--primary-color);
  animation: scan 4s linear infinite;
}

@keyframes scan {
  0% { top: -5%; }
  100% { top: 105%; }
}

对比 Flutter 版的AnimatedBuilder呼吸动画,HTML 版通过纯 CSS 实现了更轻量化的背景特效,无需依赖 Flutter 的动画控制器。

3.2 故障艺术与霓虹发光

/* 故障艺术效果 */
.glitch::before {
  left: 2px;
  text-shadow: -1px 0 var(--secondary-color);
  clip: rect(24px, 550px, 90px, 0);
  animation: glitch-anim 2s infinite linear alternate-reverse;
}

/* 霓虹发光按钮 */
.cta-btn:hover {
  color: #050505;
  background: var(--primary-color);
  box-shadow: 0 0 20px var(--primary-color), inset 0 0 20px rgba(255,255,255,0.2);
}

通过text-shadowbox-shadow实现的霓虹发光效果,是科技感 UI 的核心视觉标识,而 Flutter 版则需要通过ShaderMask或自定义 Paint 来模拟类似效果。

3.3 交互与动画触发

// 技能条滚动触发动画
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const width = entry.target.getAttribute('data-width');
      entry.target.style.width = width;
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.5 });

skillBars.forEach(bar => observer.observe(bar));

对比 Flutter 版的AnimationController,HTML 版通过IntersectionObserver实现了更轻量化的滚动触发动画,无需依赖 Flutter 的状态管理。

全部代码如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TECH SYSTEM | 个人主页</title>
    <!-- 引入科技感字体 Orbitron -->
    <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Rajdhani:wght@300;500;700&display=swap" rel="stylesheet">
    <style>
        /* --- 全局变量定义 --- */
        :root {
            --bg-color: #050505;
            --text-color: #e0e0e0;
            --primary-color: #00f3ff; /* 电光青 */
            --secondary-color: #bc13fe; /* 霓虹紫 */
            --accent-color: #2dff00; /* 终端绿 */
            --card-bg: rgba(20, 20, 30, 0.7);
            --border-glow: 0 0 10px var(--primary-color), inset 0 0 5px var(--primary-color);
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Rajdhani', sans-serif;
            background-color: var(--bg-color);
            color: var(--text-color);
            overflow-x: hidden;
            line-height: 1.6;
        }

        /* --- 背景网格效果 --- */
        .grid-bg {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-image: 
                linear-gradient(rgba(0, 243, 255, 0.05) 1px, transparent 1px),
                linear-gradient(90deg, rgba(0, 243, 255, 0.05) 1px, transparent 1px);
            background-size: 50px 50px;
            z-index: -1;
            pointer-events: none;
        }

        /* --- 扫描线动画 --- */
        .scanline {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 5px;
            background: rgba(0, 243, 255, 0.3);
            box-shadow: 0 0 15px var(--primary-color);
            z-index: 1000;
            pointer-events: none;
            animation: scan 4s linear infinite;
        }

        @keyframes scan {
            0% { top: -5%; }
            100% { top: 105%; }
        }

        /* --- 导航栏 --- */
        nav {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px 5%;
            background: rgba(5, 5, 5, 0.8);
            backdrop-filter: blur(10px);
            border-bottom: 1px solid rgba(0, 243, 255, 0.2);
            position: fixed;
            width: 100%;
            top: 0;
            z-index: 100;
        }

        .logo {
            font-family: 'Orbitron', sans-serif;
            font-weight: 900;
            font-size: 1.8rem;
            color: var(--primary-color);
            text-shadow: 0 0 10px var(--primary-color);
            letter-spacing: 2px;
        }

        .nav-links {
            list-style: none;
            display: flex;
            gap: 30px;
        }

        .nav-links a {
            text-decoration: none;
            color: var(--text-color);
            font-weight: 500;
            font-size: 1.1rem;
            text-transform: uppercase;
            letter-spacing: 1px;
            position: relative;
            padding: 5px 0;
        }

        .nav-links a::after {
            content: '';
            position: absolute;
            width: 0;
            height: 2px;
            bottom: 0;
            left: 0;
            background-color: var(--primary-color);
            box-shadow: 0 0 5px var(--primary-color);
            transition: width 0.3s;
        }

        .nav-links a:hover {
            color: var(--primary-color);
        }

        .nav-links a:hover::after {
            width: 100%;
        }

        /* --- Hero 区域 --- */
        .hero {
            height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
            position: relative;
        }

        .hero-title {
            font-family: 'Orbitron', sans-serif;
            font-size: 4rem;
            font-weight: 900;
            margin-bottom: 20px;
            text-transform: uppercase;
            position: relative;
            color: #fff;
        }

        /* 故障艺术效果 */
        .glitch {
            position: relative;
        }
        
        .glitch::before, .glitch::after {
            content: attr(data-text);
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }

        .glitch::before {
            left: 2px;
            text-shadow: -1px 0 var(--secondary-color);
            clip: rect(24px, 550px, 90px, 0);
            animation: glitch-anim 2s infinite linear alternate-reverse;
        }

        .glitch::after {
            left: -2px;
            text-shadow: -1px 0 var(--primary-color);
            clip: rect(85px, 550px, 140px, 0);
            animation: glitch-anim2 3s infinite linear alternate-reverse;
        }

        @keyframes glitch-anim {
            0% { clip: rect(30px, 9999px, 10px, 0); }
            20% { clip: rect(15px, 9999px, 100px, 0); }
            40% { clip: rect(50px, 9999px, 20px, 0); }
            60% { clip: rect(80px, 9999px, 120px, 0); }
            80% { clip: rect(10px, 9999px, 60px, 0); }
            100% { clip: rect(40px, 9999px, 90px, 0); }
        }

        @keyframes glitch-anim2 {
            0% { clip: rect(60px, 9999px, 10px, 0); }
            20% { clip: rect(100px, 9999px, 30px, 0); }
            40% { clip: rect(10px, 9999px, 80px, 0); }
            60% { clip: rect(30px, 9999px, 50px, 0); }
            80% { clip: rect(90px, 9999px, 10px, 0); }
            100% { clip: rect(20px, 9999px, 70px, 0); }
        }

        .hero-subtitle {
            font-size: 1.5rem;
            color: var(--primary-color);
            margin-bottom: 40px;
            letter-spacing: 3px;
            text-shadow: 0 0 5px rgba(0, 243, 255, 0.5);
        }

        .cta-btn {
            padding: 15px 40px;
            background: transparent;
            border: 2px solid var(--primary-color);
            color: var(--primary-color);
            font-family: 'Orbitron', sans-serif;
            font-weight: 700;
            text-transform: uppercase;
            cursor: pointer;
            position: relative;
            overflow: hidden;
            transition: color 0.3s, box-shadow 0.3s;
            text-decoration: none;
            display: inline-block;
        }

        .cta-btn:hover {
            color: #050505;
            background: var(--primary-color);
            box-shadow: 0 0 20px var(--primary-color), inset 0 0 20px rgba(255,255,255,0.2);
        }

        /* --- 通用区块样式 --- */
        .section {
            padding: 100px 10%;
        }

        .section-title {
            font-family: 'Orbitron', sans-serif;
            font-size: 2.5rem;
            color: var(--primary-color);
            margin-bottom: 50px;
            text-align: center;
            text-transform: uppercase;
            position: relative;
        }

        .section-title::after {
            content: '';
            display: block;
            width: 100px;
            height: 2px;
            background: var(--secondary-color);
            margin: 10px auto;
            box-shadow: 0 0 10px var(--secondary-color);
        }

        /* --- 技能区域 --- */
        .skills-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 30px;
        }

        .skill-card {
            background: var(--card-bg);
            border: 1px solid rgba(0, 243, 255, 0.1);
            padding: 30px;
            position: relative;
            transition: transform 0.3s, border-color 0.3s;
            clip-path: polygon(0 0, 100% 0, 100% 85%, 90% 100%, 0 100%); /* 切角效果 */
        }

        .skill-card:hover {
            transform: translateY(-5px);
            border-color: var(--primary-color);
            box-shadow: 0 0 15px rgba(0, 243, 255, 0.1);
        }

        .skill-card h3 {
            font-family: 'Orbitron', sans-serif;
            color: var(--primary-color);
            margin-bottom: 15px;
            font-size: 1.2rem;
        }

        .skill-bar {
            height: 5px;
            background: rgba(255, 255, 255, 0.1);
            margin-top: 10px;
            position: relative;
        }

        .skill-progress {
            height: 100%;
            background: var(--primary-color);
            box-shadow: 0 0 10px var(--primary-color);
            width: 0; /* 动画初始值 */
            transition: width 1.5s ease-in-out;
        }

        /* --- 项目区域 --- */
        .projects-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 30px;
        }

        .project-card {
            background: linear-gradient(135deg, rgba(20,20,30,0.9), rgba(10,10,15,0.9));
            border: 1px solid rgba(255, 255, 255, 0.05);
            overflow: hidden;
            position: relative;
            transition: 0.3s;
        }

        .project-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(0, 243, 255, 0.1), transparent);
            transition: 0.5s;
        }

        .project-card:hover::before {
            left: 100%;
        }

        .project-content {
            padding: 30px;
            border-top: 2px solid transparent;
            transition: border-color 0.3s;
        }

        .project-card:hover .project-content {
            border-top-color: var(--secondary-color);
        }

        .project-title {
            font-family: 'Orbitron', sans-serif;
            font-size: 1.3rem;
            margin-bottom: 15px;
            color: #fff;
        }

        .project-desc {
            font-size: 0.95rem;
            color: #aaa;
            margin-bottom: 20px;
        }

        .tag {
            display: inline-block;
            padding: 4px 8px;
            background: rgba(0, 243, 255, 0.1);
            color: var(--primary-color);
            font-size: 0.8rem;
            border: 1px solid rgba(0, 243, 255, 0.2);
            margin-right: 5px;
            margin-bottom: 5px;
        }

        /* --- 页脚 --- */
        footer {
            padding: 50px 5%;
            background: rgba(0, 0, 0, 0.8);
            text-align: center;
            border-top: 1px solid rgba(0, 243, 255, 0.1);
        }

        .footer-text {
            font-family: 'Orbitron', sans-serif;
            color: #555;
            font-size: 0.8rem;
            letter-spacing: 2px;
        }

        /* --- 响应式 --- */
        @media (max-width: 768px) {
            .hero-title {
                font-size: 2.5rem;
            }
            .nav-links {
                display: none; /* 移动端简化 */
            }
        }
    </style>
</head>
<body>

    <!-- 背景特效层 -->
    <div class="grid-bg"></div>
    <div class="scanline"></div>

    <!-- 导航栏 -->
    <nav>
        <div class="logo">PORTFOLIO.IO</div>
        <ul class="nav-links">
            <li><a href="#home">Home</a></li>
            <li><a href="#skills">Skills</a></li>
            <li><a href="#projects">Projects</a></li>
            <li><a href="#contact">Contact</a></li>
        </ul>
    </nav>

    <!-- Hero 区域 -->
    <section class="hero" id="home">
        <h1 class="hero-title glitch" data-text="FUTURE IS NOW">FUTURE IS NOW</h1>
        <p class="hero-subtitle">// FULL STACK DEVELOPER & UI DESIGNER //</p>
        <a href="#projects" class="cta-btn">Initialize System</a>
    </section>

    <!-- 技能区域 -->
    <section class="section" id="skills">
        <h2 class="section-title">System Modules</h2>
        <div class="skills-grid">
            <div class="skill-card">
                <h3>Frontend Architecture</h3>
                <p>React, Vue, Three.js 构建高性能交互界面。</p>
                <div class="skill-bar"><div class="skill-progress" data-width="90%"></div></div>
            </div>
            <div class="skill-card">
                <h3>Backend Logic</h3>
                <p>Node.js, Python, Go 数据处理与API设计。</p>
                <div class="skill-bar"><div class="skill-progress" data-width="85%"></div></div>
            </div>
            <div class="skill-card">
                <h3>UI/UX Design</h3>
                <p>Figma, After Effects 赛视觉与动效设计。</p>
                <div class="skill-bar"><div class="skill-progress" data-width="80%"></div></div>
            </div>
        </div>
    </section>

    <!-- 项目区域 -->
    <section class="section" id="projects">
        <h2 class="section-title">Data Logs</h2>
        <div class="projects-grid">
            <div class="project-card">
                <div class="project-content">
                    <h3 class="project-title">Project: Cyberpunk-Dash</h3>
                    <p class="project-desc">一个基于WebGL的数据可视化仪表盘,具有强烈的赛博朋克风格。</p>
                    <span class="tag">Three.js</span>
                    <span class="tag">React</span>
                    <span class="tag">WebGL</span>
                </div>
            </div>
            <div class="project-card">
                <div class="project-content">
                    <h3 class="project-title">Project: Neural-Net</h3>
                    <p class="project-desc">模拟神经网络运算过程的交互式教育网站。</p>
                    <span class="tag">Python</span>
                    <span class="tag">TensorFlow</span>
                </div>
            </div>
            <div class="project-card">
                <div class="project-content">
                    <h3 class="project-title">Project: E-Commerce</h3>
                    <p class="project-desc">高并发电商系统架构设计与实现。</p>
                    <span class="tag">Go</span>
                    <span class="tag">Microservices</span>
                </div>
            </div>
        </div>
    </section>

    <!-- 页脚 -->
    <footer id="contact">
        <p class="footer-text">SYSTEM STATUS: ONLINE // VERSION 2.0.1 // &copy; 2023 TECH PORTFOLIO</p>
    </footer>

    <script>
        // 简单的打字机效果逻辑可以在这里添加
        // 这里主要实现技能条动画的触发

        // 观察技能条进入视口
        const skillBars = document.querySelectorAll('.skill-progress');
        
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const width = entry.target.getAttribute('data-width');
                    entry.target.style.width = width;
                    observer.unobserve(entry.target);
                }
            });
        }, { threshold: 0.5 });

        skillBars.forEach(bar => {
            observer.observe(bar);
        });

        // 导航栏平滑滚动
        document.querySelectorAll('a[href^="#"]').forEach(anchor => {
            anchor.addEventListener('click', function (e) {
                e.preventDefault();
                document.querySelector(this.getAttribute('href')).scrollIntoView({
                    behavior: 'smooth'
                });
            });
        });
    </script>
</body>
</html>

4 本地效果验证:从 Flutter 到 HTML 的跨栈调试

4.1 项目创建与代码替换

  1. 新建文件夹tech_mood_ui,将 GLM-5 生成的 HTML 代码保存为test.html
  2. 用 VS Code 打开文件夹,通过 Live Server 插件启动本地服务(端口 5500),点击右下角Go Live即可运行;
  3. 浏览器访问http://localhost:5500/test.html,也可验证科技感 UI 效果。

4.2 效果验证要点

  • 视觉特效:网格背景、扫描线、故障标题均正常显示,霓虹发光效果清晰;
  • 交互反馈:按钮 hover 时填充发光,技能条滚动时自动填充,导航链接平滑滚动;
  • 响应式适配:移动端自动隐藏导航链接,布局无错乱。

4.3 运行效果展示

5 实践感悟

  1. AI 迭代效率:从 “开心版” 到 “科技感版”,GLM-5 在 10 分钟内完成了从需求分析到代码生成的全流程,传统开发中至少需要数小时的风格重构,大幅降低了 UI 迭代门槛;
  2. 跨栈适配能力:GLM-5 能根据技术栈(Flutter/HTML)自动调整实现方式,既保证了效果落地,又适配了不同平台的开发习惯;
  3. 参数的核心作用Max TokensTemperature的精准设置,是 AI 完整输出复杂特效代码的关键,避免了因截断导致的效果缺失。

参与链接

GLM-5 在线体验:https://ai.atomgit.com/zai-org/GLM-5/model-inference

GLM-5 活动贴:https://ai.atomgit.com/zai-org/GLM-5/discussions

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐