最近,有一个比较火的很有趣且灵动的登录页火了。
- 角色视觉跟随鼠标
- 输入框打字时扯脖子瞅
- 显示密码明文时避开视线
已经有大神(katavii)复刻了动画效果,并在github上开源了:https://github.com/katavii/animated-login ,基于React实现。
如果你的项目是用Vue开发的,可以考虑用AI将此项目转换成了Vue3的语法写法。
最简单的方式,直接用Claude Code一句话就能完成,根据模型能力,你可能需要多次调试。- claude帮我把这个项目转成vue3 + ant-design-vue的前端项目
复制代码 以下是我的转换代码,如果你的AI代码没有调试成功,可以参考下。
创建项目
现在开发前端项目,肯定首选Vite。- pnpm create vite# 选择Vue模板、TypeScript语法
复制代码
封装组件
在src/components/创建animated-characters文件夹
EyeBall
创建 src/components/animated-characters/EyeBall.vue,制作动画的大眼睛。
Pupil
创建 src/components/animated-characters/Pupil.vue,制作动画的小眼睛。
角色
安装依赖创建 src/components/animated-characters/Index.vue,制作动画的角色。- props属性- is-typing 是否正在输入- show-password 显示密码明文- password-length 密码输入框是否有值
复制代码
登录页
安装依赖- pnpm install --save ant-design-vue @ant-design/icons-vue
复制代码 在src/main.js添加以下内容- import Antd from 'ant-design-vue'import 'ant-design-vue/dist/reset.css'app.use(Antd)
复制代码 创建 src/pages/login/Index.vue,登录页。- Nexus 帮助中心 隐私政策 Nexus 平台 [size=6]登录到工作台[/size]
- 统一接入前端平台旗下所有系统
- 账号 密码 {{ error }} {{ loading ? '登录中...' : '登录' }} 或 飞书账号一键登录 暂无账号? 联系管理员申请开通
复制代码 创建 src/pages/login/index.module.css,登录页样式。- .container { min-height: 100vh; display: grid; grid-template-columns: 1fr 1fr;}@media (max-width: 1024px) { .container { grid-template-columns: 1fr; }}/* ─── 左侧面板 ───────────────────────────────────────────────────────────────── */.leftPanel { position: relative; display: flex; flex-direction: column; justify-content: space-between; padding: 48px; background: linear-gradient(145deg, #0f172a 0%, #1e3a8a 50%, #1e40af 100%); overflow: hidden;}@media (max-width: 1024px) { .leftPanel { display: none; }}.leftTop { position: relative; z-index: 20; display: flex; align-items: center; gap: 10px; font-size: 20px; font-weight: 700; color: #ffffff; letter-spacing: 0.5px;}.brandMark { width: 40px; height: 40px; border-radius: 10px; background: rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.2); display: flex; align-items: center; justify-content: center; flex-shrink: 0; backdrop-filter: blur(8px);}.brandName { color: #ffffff; font-size: 20px; font-weight: 700; letter-spacing: 1px;}.charactersArea { position: relative; z-index: 20; display: flex; align-items: flex-end; justify-content: center; height: 500px;}.leftFooter { position: relative; z-index: 20; display: flex; align-items: center; gap: 24px;}.leftFooter a { font-size: 13px; color: rgba(255, 255, 255, 0.45); text-decoration: none; transition: color 0.2s; cursor: pointer;}.leftFooter a:hover { color: rgba(255, 255, 255, 0.85);}.decorBlur1 { position: absolute; top: 15%; right: 10%; width: 300px; height: 300px; background: rgba(59, 130, 246, 0.25); border-radius: 50%; filter: blur(80px); pointer-events: none; z-index: 0;}.decorBlur2 { position: absolute; bottom: 10%; left: 5%; width: 400px; height: 400px; background: rgba(30, 64, 175, 0.3); border-radius: 50%; filter: blur(100px); pointer-events: none; z-index: 0;}.decorGrid { position: absolute; inset: 0; background-image: linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px); background-size: 40px 40px; pointer-events: none; z-index: 1;}/* ─── 右侧面板 ───────────────────────────────────────────────────────────────── */.rightPanel { display: flex; align-items: center; justify-content: center; padding: 32px; background: #ffffff;}.formWrapper { width: 100%; max-width: 400px;}.mobileLogo { display: none; align-items: center; justify-content: center; gap: 8px; font-size: 18px; font-weight: 700; color: #0f172a; margin-bottom: 48px;}@media (max-width: 1024px) { .mobileLogo { display: flex; }}.mobileLogoIcon { width: 32px; height: 32px; border-radius: 8px; background: #eff6ff; display: flex; align-items: center; justify-content: center;}.formHeader { text-align: center; margin-bottom: 40px;}.formTitle { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; color: #0f172a; margin: 0 0 10px 0; line-height: 1.3;}.formSubtitle { font-size: 14px; color: #6b7280; margin: 0; line-height: 1.6;}.form :global(.ant-form-item) { margin-bottom: 20px;}.form :global(.ant-input-affix-wrapper) { height: 48px !important; background: #fafafa !important; border: 1px solid #e5e7eb !important; border-radius: 10px !important; transition: border-color 0.2s, box-shadow 0.2s !important;}.form :global(.ant-input-affix-wrapper:hover) { border-color: #3b82f6 !important;}.form :global(.ant-input-affix-wrapper:focus),.form :global(.ant-input-affix-wrapper-focused) { border-color: #1e40af !important; box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.08) !important; background: #ffffff !important;}.form :global(.ant-input-affix-wrapper .ant-input) { background: transparent !important; font-size: 14px !important; color: #111827 !important;}.form :global(.ant-input-affix-wrapper .ant-input::placeholder) { color: #c0c4cc !important;}.form :global(.ant-form-item-explain-error) { font-size: 13px !important; margin-top: 4px !important;}.fieldLabel { font-size: 13px; font-weight: 500; color: #374151; margin-bottom: 6px; letter-spacing: 0.2px;}.prefixIcon { color: #b0b7c3; font-size: 15px;}.eyeToggle { color: #6b7280; cursor: pointer; font-size: 16px; display: flex; align-items: center; transition: color 0.2s;}.eyeToggle:hover { color: #374151;}.errorBox { padding: 10px 14px; font-size: 13px; color: #dc2626; background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; margin-bottom: 16px;}.submitBtn { height: 48px !important; font-size: 15px !important; font-weight: 600 !important; border-radius: 10px !important; background: #1e40af !important; border-color: #1e40af !important; letter-spacing: 1px; transition: background 0.2s, opacity 0.2s !important; cursor: pointer;}.submitBtn:hover { background: #1d4ed8 !important; border-color: #1d4ed8 !important; opacity: 1 !important;}.submitBtn:active { opacity: 0.85 !important;}.divider { display: flex; align-items: center; gap: 12px; margin: 20px 0 0; color: #d1d5db; font-size: 13px;}.divider::before,.divider::after { content: ''; flex: 1; height: 1px; background: #e5e7eb;}.divider span { color: #9ca3af; white-space: nowrap;}.googleBtn { height: 48px !important; font-size: 14px !important; border-radius: 10px !important; margin-top: 12px !important; background: #ffffff !important; border: 1px solid #e5e7eb !important; color: #374151 !important; transition: background 0.2s, border-color 0.2s !important; cursor: pointer;}.googleBtn:hover { background: #eff6ff !important; border-color: rgba(30, 64, 175, 0.25) !important; color: #1e40af !important;}.signupRow { text-align: center; font-size: 13px; color: #6b7280; margin-top: 28px;}.signupLink { color: #1e40af; font-weight: 500; text-decoration: none; cursor: pointer;}.signupLink:hover { text-decoration: underline; color: #1d4ed8;}
复制代码 源代码
- GitHub:https://github.com/BugShare404/animated-login
- Gitee:https://gitee.com/bugshare/animated-login
vue2分支是Vue2 + Element-ui实现。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |