说出来你可能不信,我最近做了一个"Loading 动画生成器",但过程完全没有动手写 CSS ------我只说了三个词:
"科技感、电波、液体。"
然后,Trae 就给我整了一个又酷又顺滑的 Loading 动画,带点赛博风、视觉流动感特别强,放在页面上那叫一个带感。整个过程几乎没写代码,完全是"我说它做"。
今天就来分享一下我是怎么一步步,用 Trae 搭出来这样一个充满创意的 Loading 动画生成器的。
🎯 起因:千篇一律的 Loading 太没意思了
现在的很多网页加载动画,不外乎:
- 一个圆圈在原地转;
- 三个点上下跳;
- 进度条一点点动。
虽然实用,但看多了真的审美疲劳。
而我希望实现一种"更有风格的加载反馈",比如说:
- 像电流在跳动,或雷达扫描;
- 有液体在流动、涌动的感觉;
- 有些像 sci-fi 界面的动态元素;
- 最好可以自动生成多个风格,选一个最喜欢的就用。
以前要做这种动效,CSS + JS + 调动画 timing function,真的要写到怀疑人生。现在我只需要把这三种感觉说出来,剩下的交给 Trae。
🧠 我输入的就是这三个词:
在 Trae IDE 的命令窗口,我只输入了这样一句:
"生成一个创意 loading 动画,风格包含:科技感、电波、液体。"
不用写详细需求,不需要动画时长、easing 曲线这些细节,Trae 自己理解这三个词的"语义背后"。

然后,它真的就给我生成了一段 CSS 动画和完整的 Loading 结构。

✨ Trae 生成的效果有多惊艳?
生成出来的动画,真的有点出乎我意料:
- 科技感:整体配色是暗背景 + 荧光蓝动画线条,像极了控制台界面;
- 电波感:主视觉是一个循环波形在水平方向上震荡,像音频频谱在跳;
- 液体感:波形线条带点弹性,有"流动"的缓动感,透明度也随着动画渐变,有种液体涟漪的效果;
- 自适应:放大缩小时,动画依旧平滑,适配性强;
- 结构干净:使用的是纯 CSS 动画 + HTML div,无 JS 依赖;
- 可嵌入组件:生成的是一个独立的 UI 片段,直接拖进页面中就能用。
我稍微把它封装成一个组件,直接就可以作为 Loading 效果用了。
我怎么把它做成"生成器"?
为了不每次都在命令窗口复制,我用 Trae 构建了一个小型前端工具,做成了"Loading 动画生成器"。主要包含:
- 一个输入框:让用户随意输入风格关键词;
- 一个预览区域:实时展示动画效果;
- 一个"复制 CSS"按钮:可以直接提取生成代码;
- 一个下载按钮:导出 HTML + CSS 文件作为片段使用;
- 多套风格模板:从"简约动效"到"暗黑科技"应有尽有。
整个前端界面也是 Trae 自动生成的,我只做了少量调整,比如换了下配色和 logo。

用 Trae 打造"表达即生成"的 UI 工具
从这个项目我真切地感受到 Trae 的一个核心能力:
你只要清晰地表达风格和感受,它就能把你的描述变成视觉呈现。
这在传统开发模式里几乎不可能:一个前端同学要先和产品开会讨论动效、再去设计、再调 CSS、再评审,现在只需要你把脑海里的画面翻译成几个关键词,就能生成接近你想法的成品。

我从"我想做个带科技感的加载动画"到"我做完了一个可以商用的 loading 组件",整个过程就花了不到半小时。
Trae,让 UI 设计更像写诗
我现在越来越相信,未来的开发一定会向"意图驱动"靠近。我们不再一行行写样式,而是描述我们想要什么,工具来做余下的工作。
Trae 做到的,不只是代码自动化,而是审美风格的理解能力 ------ 从"科技感"三个字里,它知道你可能想要霓虹色、微光、对称性、流动性,然后把它表达成视觉。
想象一下以后:你写出"复古 80 年代电影片头感"的 loading,它也能给你。
想试试?就一句话:
打开 Trae,输入:
"生成一个创意 loading 动画,风格包含:科技感、电波、液体。"
或者你试试自己的搭配,比如:
- "糖果风、轻快、Q 弹"
- "极简、纯白、淡出"
- "像数据流在流动"
你会发现,每一次生成都像拆盲盒一样,灵感源源不断。
如果你感兴趣,我也可以把这个"Loading 动画生成器"整理成一个可部署的页面(支持自定义导出),甚至可以作为开源小工具发出去。
欢迎来一起玩!
html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Loading 动画生成器</title>
<style>
body {
background: #111;
color: white;
font-family: sans-serif;
padding: 2rem;
text-align: center;
}
input {
padding: 0.5rem 1rem;
width: 300px;
font-size: 16px;
border-radius: 8px;
border: none;
}
button {
margin: 1rem 0.5rem;
padding: 0.5rem 1rem;
font-size: 14px;
border: none;
border-radius: 6px;
cursor: pointer;
background: #444;
color: white;
}
.preview {
margin-top: 2rem;
min-height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
.code-box {
background: #222;
color: #0f0;
text-align: left;
margin: 1rem auto;
padding: 1rem;
white-space: pre;
width: 90%;
display: none;
}
.style-list {
margin-top: 2rem;
}
.style-list button {
margin: 0.3rem;
background: #333;
}
</style>
</head>
<body>
<h1>🔮 Loading 动画生成器</h1>
<input id="keywordInput" placeholder="输入关键词,例如:液体、科技、闪烁" />
<br>
<button onclick="generate()">生成动画</button>
<button onclick="copyCSS()">复制 CSS</button>
<button onclick="download()">下载 HTML + CSS</button>
<div class="preview" id="previewArea"></div>
<div class="code-box" id="codeBox"></div>
<div class="style-list">
<p>🎨 快速预览:</p>
<button onclick="quickLoad('液体')">液体</button>
<button onclick="quickLoad('闪烁')">闪烁</button>
<button onclick="quickLoad('科技')">科技</button>
<button onclick="quickLoad('蒸汽波')">蒸汽波</button>
<button onclick="quickLoad('几何')">几何</button>
<button onclick="quickLoad('金属')">金属</button>
<button onclick="quickLoad('柔光')">柔光</button>
<button onclick="quickLoad('水滴')">水滴</button>
<button onclick="quickLoad('能量环')">能量环</button>
<button onclick="quickLoad('流光')">流光</button>
</div>
<script>
const styles = {
"液体": {
html: `<div class="liquid-loader"></div>`,
css: `.liquid-loader {
width: 60px;
height: 60px;
background: radial-gradient(circle, #00f2ff, #0077be);
border-radius: 50%;
animation: drip 1.5s infinite ease-in-out;
}
@keyframes drip {
0%, 100% { transform: scale(1); opacity: 0.7; }
50% { transform: scale(1.4); opacity: 1; }
}`
},
"闪烁": {
html: `<div class="glow-loader"></div>`,
css: `.glow-loader {
width: 40px;
height: 40px;
background: #ff00ff;
border-radius: 50%;
box-shadow: 0 0 20px #ff00ff;
animation: glow 1s infinite alternate;
}
@keyframes glow {
from { opacity: 0.2; box-shadow: 0 0 5px #ff00ff; }
to { opacity: 1; box-shadow: 0 0 20px #ff00ff; }
}`
},
"科技": {
html: `<div class="tech-loader"></div>`,
css: `.tech-loader {
width: 60px;
height: 10px;
background: linear-gradient(90deg, #0ff, #00f, #0ff);
background-size: 200% auto;
animation: scan 1s linear infinite;
}
@keyframes scan {
0% { background-position: 0% 0; }
100% { background-position: 200% 0; }
}`
},
"蒸汽波": {
html: `<div class="vaporwave-loader"></div>`,
css: `.vaporwave-loader {
width: 0; height: 0;
border-left: 30px solid transparent;
border-right: 30px solid transparent;
border-bottom: 60px solid #ff66cc;
animation: blink 1s infinite alternate;
}
@keyframes blink {
0% { opacity: 0.5; }
100% { opacity: 1; }
}`
},
"几何": {
html: `<div class="geo-loader"></div>`,
css: `.geo-loader {
width: 40px;
height: 40px;
background: #f0f;
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
animation: geo 1s infinite ease-in-out;
}
@keyframes geo {
0%, 100% { transform: rotate(0deg); }
50% { transform: rotate(180deg); }
}`
},
"金属": {
html: `<div class="metal-loader"></div>`,
css: `.metal-loader {
width: 50px;
height: 50px;
border: 6px solid #999;
border-top: 6px solid #ccc;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}`
},
"柔光": {
html: `<div class="soft-loader"></div>`,
css: `.soft-loader {
width: 50px;
height: 50px;
background: rgba(255,255,255,0.1);
border-radius: 50%;
box-shadow: 0 0 30px rgba(255,255,255,0.5);
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 0.5; }
50% { transform: scale(1.2); opacity: 1; }
}`
},
"水滴": {
html: `<div class="drop-loader"></div>`,
css: `.drop-loader {
width: 20px;
height: 20px;
border-radius: 50%;
background: #0ff;
animation: drop 1s ease-in-out infinite;
}
@keyframes drop {
0% { transform: translateY(0); }
50% { transform: translateY(20px); }
100% { transform: translateY(0); }
}`
},
"能量环": {
html: `<div class="ring-loader"></div>`,
css: `.ring-loader {
width: 50px;
height: 50px;
border: 4px dashed #0ff;
border-radius: 50%;
animation: ring 1s linear infinite;
}
@keyframes ring {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}`
},
"流光": {
html: `<div class="shine-loader"></div>`,
css: `.shine-loader {
width: 100px;
height: 8px;
background: linear-gradient(to right, #000, #0ff, #000);
background-size: 200% auto;
animation: shine 1s linear infinite;
}
@keyframes shine {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}`
}
};
function generate() {
const keyword = document.getElementById("keywordInput").value.trim();
loadAnimation(keyword);
}
function quickLoad(name) {
document.getElementById("keywordInput").value = name;
loadAnimation(name);
}
function loadAnimation(keyword) {
const preview = document.getElementById("previewArea");
const codeBox = document.getElementById("codeBox");
const matched = styles[keyword];
if (matched) {
preview.innerHTML = matched.html;
const styleTag = `<style>\n${matched.css}\n</style>`;
codeBox.textContent = matched.html + "\n\n" + styleTag;
codeBox.style.display = "block";
codeBox.dataset.css = matched.css;
insertDynamicStyle(matched.css);
} else {
preview.innerHTML = `<p>未识别关键词,请尝试其他风格</p>`;
codeBox.style.display = "none";
}
}
function insertDynamicStyle(css) {
const oldStyle = document.getElementById("dynamic-style");
if (oldStyle) oldStyle.remove();
const style = document.createElement("style");
style.id = "dynamic-style";
style.innerHTML = css;
document.head.appendChild(style);
}
function copyCSS() {
const css = document.getElementById("codeBox").dataset.css;
if (css) {
navigator.clipboard.writeText(css);
alert("已复制 CSS 到剪贴板!");
}
}
function download() {
const html = document.getElementById("codeBox").textContent;
const blob = new Blob([html], { type: "text/html" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "loading-animation.html";
link.click();
}
</script>
</body>
</html>