当前位置: 首页 > news >正文

Vue 3动画角色登录页:从创意到优化

Vue 3 动画角色登录页面:从创意实现到性能优化

本文基于 GitHub 开源项目进行学习和优化实践,原项目地址:https://github.com/marker964/animated-characters-login-page

项目简介

今天给大家分享一个有趣的 Vue 3 登录页面项目 ——CareerCompass。这个项目的亮点在于左侧有四个可爱的动画角色,它们会根据用户的输入行为做出不同的反应:

  • 🎯眼睛跟随鼠标- 角色的眼睛会追踪鼠标移动
  • 📧输入邮箱时- 角色会变高,仿佛在关注你的输入
  • 🔐输入密码时- 角色会用手遮挡眼睛,保护隐私
  • 👀显示密码时- 角色会偷偷偷看,增添趣味性

技术栈

  • Vue 3- 使用 Composition API
  • Vite- 极速开发构建工具
  • Tailwind CSS- 现代化 CSS 框架
  • tailwindcss-animate- 动画增强插件

核心实现思路

1. 眼睛追踪原理

眼睛追踪的核心是计算鼠标相对于眼睛中心的位置,然后根据角度和距离计算瞳孔的偏移:

constcalculatePupilPosition=(eyeRef,mouseX,mouseY,maxDistance)=>{constrect=eyeRef.getBoundingClientRect()constcenterX=rect.left+rect.width/2constcenterY=rect.top+rect.height/2constdeltaX=mouseX-centerXconstdeltaY=mouseY-centerY// 限制瞳孔移动距离,防止超出眼球范围constdistance=Math.min(Math.sqrt(deltaX**2+deltaY**2),maxDistance)constangle=Math.atan2(deltaY,deltaX)return{x:Math.cos(angle)*distance,y:Math.sin(angle)*distance}}

2. 角色状态响应

通过 Vue 的响应式系统,我们可以轻松实现角色对不同状态的响应:

<script setup> const props = defineProps({ isTyping: { type: Boolean, default: false }, showPassword: { type: Boolean, default: false }, passwordLength: { type: Number, default: 0 } }) // 判断是否处于遮挡密码状态 const isHidingPassword = computed(() => props.passwordLength > 0 && !props.showPassword ) // 角色变高的条件 const shouldGrow = computed(() => props.isTyping || isHidingPassword.value ) </script>

3. 角色身体变形

使用 CSStransform: skewX()实现角色身体的倾斜效果,让角色看起来更生动:

<template> <div class="character" :style="{ transform: shouldGrow ? `skewX(${bodySkew - 12}deg) translateX(40px)` : `skewX(${bodySkew}deg)`, transformOrigin: 'bottom center' }" /> </template>

性能优化历程

在项目初版中,我发现了几个性能问题,经过优化后效果显著提升。

问题一:重复的鼠标事件监听

初版代码中,三个组件各自监听了mousemove事件:

// EyeBall.vueonMounted(()=>window.addEventListener('mousemove',onMouseMove))// Pupil.vueonMounted(()=>window.addEventListener('mousemove',onMouseMove))// AnimatedCharacters.vueonMounted(()=>window.addEventListener('mousemove',onMouseMove))

这意味着每次鼠标移动,会触发3 次事件处理!

优化方案:Composable + 单例模式

创建useMousePositioncomposable,使用单例模式共享鼠标位置:

// src/composables/useMousePosition.jsimport{ref}from'vue'// 单例:全局共享letmouseX=ref(0)letmouseY=ref(0)letisListening=falseexportfunctionuseMousePosition(){if(!isListening){window.addEventListener('mousemove',onMouseMove,{passive:true})isListening=true}return{mouseX,mouseY}}

问题二:高频事件无节流

mousemove是高频事件,每秒可能触发数十次,导致computed计算过于频繁。

优化方案:requestAnimationFrame 节流

letrafId=nullletpendingX=0letpendingY=0constonMouseMove=(e)=>{pendingX=e.clientX pendingY=e.clientY// 使用 rAF 节流,每帧最多更新一次if(!rafId){rafId=requestAnimationFrame(()=>{mouseX.value=pendingX mouseY.value=pendingY rafId=null})}}

问题三:冗长的 inline CSS class

初版 App.vue 中,input 元素的 class 超过 200 字符:

<!-- 优化前 --> <input class="login-input flex w-full rounded-full border px-4 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm h-12 bg-background border-border/60 focus:border-primary" />

优化方案:提取 CSS 类

/* src/style.css */.login-input{@applyflex w-full rounded-full border px-4 py-2 text-base ring-offset-background;@applyplaceholder:text-muted-foreground;@applyfocus-visible:outline-nonefocus-visible:ring-2focus-visible:ring-ring;@applyh-12 bg-background border-border/60;}.login-input:focus{@applyborder-primary;}
<!-- 优化后 --> <input class="login-input" />

可访问性改进

添加键盘支持

密码显示切换按钮初版只支持鼠标点击,优化后添加了键盘支持:

<button @click="showPassword = !showPassword" @keydown.enter="showPassword = !showPassword" @keydown.space.prevent="showPassword = !showPassword" class="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring" > <!-- 眼睛图标 --> </button>

本地化图片资源

初版使用外部 URL 加载 Logo 图片,存在加载失败风险:

<!-- 优化前 --> <img src="https://i-postimg.cc/nLrDYrHW/icon.png" />

优化后将图片存入本地src/assets/

<!-- 优化后 --> <img src="./assets/logo.svg" />

项目结构

src/ ├── assets/ │ └── logo.svg # 本地化 Logo ├── components/ │ ├── AnimatedCharacters.vue # 主角色组件 │ ├── EyeBall.vue # 眼球组件(带眨眼) │ ├── Pupil.vue # 瞳孔组件 │ └── InteractiveHoverButton.vue # 悬浮按钮 ├── composables/ │ ├── useMousePosition.js # 鼠标位置追踪 │ └── useEyeTracking.js # 眼睛追踪计算 ├── App.vue # 主应用 ├── main.js # 入口文件 └── style.css # 全局样式

运行项目

# 安装依赖npminstall# 启动开发服务器npmrun dev# 构建生产版本npmrun build

总结

本文基于 GitHub 开源项目进行学习和二次优化,展示了如何:

  1. 利用 Vue 3 Composition API构建响应式动画组件
  2. 通过 Composables实现逻辑复用和性能优化
  3. 使用 requestAnimationFrame节流高频事件
  4. 提取 CSS 类提高代码可维护性
  5. 注重可访问性添加键盘交互支持

GitHub 原项目地址:https://github.com/marker964/animated-characters-login-page

Gitee 优化版地址:https://gitee.com/gomes/animated-characters-login-page

如果觉得有帮助,欢迎点赞收藏!有什么问题可以在评论区讨论。

http://www.jsqmd.com/news/615705/

相关文章:

  • 创建abb机器人机械装置————简易活塞
  • 双系统Linux死机解决方法
  • 四门课程,帮您转型AI产品经理
  • OpenClaw多模型切换技巧:Qwen3-14b_int4_awq与本地小模型协同作战
  • 2026年AI搜索问答优化天花板横评:5大源头厂家综合对比+采购避坑指南
  • OpenClaw错误处理机制:Phi-3-vision识别失败自动重试方案
  • 2026年,这家质保长且免拆治理烧机油的修理厂,究竟有何过人之处?
  • Java 25虚拟线程到底多快?实测10万QPS下内存占用下降73%、吞吐提升4.8倍,附压测脚本与GraalVM调优清单
  • 《数论探微:进阶版》(Arithmetic Tales: Advanced Edition)暗
  • HagiCode Desktop 混合分发架构解析:如何用 PP 加速大文件下载皇
  • ki1.me/cat/2 ai模型充值网站
  • 一文学习 工作流开发 BPMN、 Flowable钾
  • IOFILE结构体的介绍与House of orange瘫
  • 重构教育评价体系:OCRAutoScore智能阅卷系统的技术革新与实践路径
  • nvm-windows兼容性深度解析:系统适配与版本管理实践指南
  • CSS如何利用Grid重写老旧的表格布局
  • OpenClaw飞书机器人配置:Qwen3-4B模型接入与对话触发
  • windows卸载mysql教程
  • linux个人心得24 (mysql③,AI排版尝试)
  • Claude 技术深度解析:使用技巧与优势
  • 2026年正规考试系统TOP5推荐覆盖多行业场景:考试系统生产厂家、智能化考试系统、水平式考试系统厂家、移动考试系统厂家选择指南 - 优质品牌商家
  • 免费AIGC降重工具实测:智能改写+AI消痕全场景覆盖
  • 2026年绵阳起重机设备改造厂家盘点:绵阳起重设备操作人员办证、绵阳起重设备租赁、绵阳路桥起重机、绵阳钢结构安装公司选择指南 - 优质品牌商家
  • OpenClaw配置文件详解:千问3.5-35B-A3B-FP8模型参数优化
  • AI模型基础
  • AI开发-python-langchain框架(--AI 直接生成并执行 Python 代码 )窖
  • 500行代码还原儿时经典 Python Pygame 制作带 AI 决策的飞行棋
  • OCAD应用:多重转换式断续变焦系统设计
  • Golang如何做DNS查询_Golang DNS解析教程【精选】
  • Less如何实现CSS主题动态切换_利用变量定义与覆盖机制