稀土掘金技术社区 05月15日 17:00
从0到1打造会催你搬砖的3D桌面宠物:Electron + Vue3实战心得
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了一款名为“小桌宠”的跨平台桌面应用,它将3D宠物与任务管理结合,提供趣味提醒功能。该项目已开源,核心技术包括透明窗口、跨进程通信、3D宠物交互系统、任务管理系统和提醒系统,并分享了性能优化实践。文章详细阐述了这些技术的实现方案和避坑指南,为开发者提供了有价值的参考。

🐰透明窗口与跨进程通信:通过`transparent: true`和`frame: false`实现无边框透明窗口,`alwaysOnTop: true`实现窗口置顶,并通过IPC通信控制子窗口状态,解决了透明窗口的点击穿透问题。

🐇3D宠物交互系统:使用TresJS加载骨骼动画模型,利用AnimationMixer实现打招呼、运动、休息状态切换,并处理点击事件穿透,通过空闲状态自动降帧和离屏时暂停渲染进行性能优化。

🐱任务管理系统:基于Dexie.js设计数据库,包括任务和提醒表,实现任务的添加、更新和智能排序,支持自动过期检测和离线存储,并提供了典型查询示例。

🐼提醒系统:采用多窗口协同架构,主窗口轮询检查提醒,提醒窗口管理队列并展示动画效果,通过IPC消息流实现提醒窗口的显示和隐藏,利用Vue TransitionGroup和CSS Keyframe实现卡片弹出效果。

🐻性能优化实践:在窗口管理、3D渲染、数据库和打包优化等方面进行实践,例如采用子窗口单例模式、离屏Canvas+按需渲染、批量操作+索引优化,以及electron-builder多平台构建配置。

原创 zlmic 2025-05-15 08:31 重庆

点击关注公众号,“技术干货” 及时达!

点击关注公众号,“技术干货” 及时达!

当二次元遇上生产力工具

最近开发了一款名为"小桌宠"的跨平台桌面应用,将3D宠物与任务管理结合。这只兔子不仅能卖萌,还会在你摸鱼时弹出提醒,堪称赛博监工。

项目已开源,欢迎star!

https://github.com/zlmica/3d-desktop-pet,

「懒得自己运行程序也可以直接到视频介绍下方获取安装包体验,支持多平台」

分享几个关键技术点的实现方案:


一、透明窗口与跨进程通信(核心黑科技)

「实现效果」:宠物始终置顶显示,右键菜单唤起任务/提醒窗口

function createWindow() {  const primaryDisplay = screen.getPrimaryDisplay()  const { width: screenWidth, height: screenHeight } =    primaryDisplay.workAreaSize  win = new BrowserWindow({    icon: path.join(process.env.VITE_PUBLIC, 'rabbit.png'),    webPreferences: {      preload: path.join(__dirname, 'preload.mjs'),    },    width: 180,    height: 200,    x: screenWidth - 200,    y: screenHeight - 150,    autoHideMenuBar: true,    transparent: true,    frame: false,    alwaysOnTop: true,    resizable: false,    hasShadow: false,  })  // Test active push message to Renderer-process.  win.webContents.on('did-finish-load', () => {    win?.webContents.send('main-process-message', new Date().toLocaleString())  })  if (VITE_DEV_SERVER_URL) {    win.loadURL(VITE_DEV_SERVER_URL)  } else {    win.loadFile(path.join(RENDERER_DIST, 'index.html'))  }  win.setVisibleOnAllWorkspaces(true, {    visibleOnFullScreen: true,  })

关键代码解读:

    transparent: true

     + 

    frame: false

     实现无边框透明窗口

    alwaysOnTop: true

     实现窗口置顶

    IPC通信控制子窗口状态

「避坑指南」:透明窗口的点击穿透问题通过计算鼠标位置+动态调整窗口大小解决


二、3D宠物交互系统(TresJS魔法)

「模型加载与动画控制」

const isPlaying = ref(false)const play = async () => {  currentAction2.value.play()  isPlaying.value = true}const sleep = () => {  currentAction2.value.stop()  isPlaying.value = false}const hello = () => {  if (isPlaying.value) {    currentAction2.value.stop()  }  currentAction.value.reset()  currentAction.value.play()  currentAction.value.setLoop(THREE.LoopOnce, 1)  currentAction.value.clampWhenFinished = true  currentAction.value.getMixer().addEventListener('finished', () => {    currentAction.value.stop()    if (isPlaying.value) {      currentAction2.value.play()    }  })}

    使用GLTFLoader加载骨骼动画模型

    AnimationMixer实现打招呼/运动/休息状态切换

    点击事件穿透处理:将3D对象坐标转换为屏幕坐标

「性能优化」

    空闲状态自动降帧(30FPS → 15FPS)

    离屏时暂停渲染


三、任务管理系统(Dexie.js实战)

「数据库设计」

class PetAppDB extends Dexie {  tasks!: Table<Task>  reminders!: Table<Reminder>  constructor() {    super('petApp')    // 定义数据库表结构和索引    this.version(1).stores({      tasks: '++id, title, status, priority, createdAt, updatedAt, dueDate',      reminders:        '++id, title, reminderTime, repeatType, isEnabled, lastAcknowledgedAt, createdAt',    })  }  /**   * 添加任务   * @param {Omit<Task, 'id' | 'createdAt' | 'updatedAt'>} task - 任务数据   * @returns {Promise<string>} 返回新增任务的ID   */  async addTask(task: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>) {    const timestamp = Date.now()    return await this.tasks.add({      ...task,      createdAt: timestamp,      updatedAt: timestamp,    })  }  /**   * 更新任务   * @param {string} id - 任务ID   * @param {Partial<Omit<Task, 'id' | 'createdAt'>>} changes - 更新的字段   * @returns {Promise<number>} 返回更新的记录数   */  async updateTask(    id: string,    changes: Partial<Omit<Task, 'id' | 'createdAt'>>  ) {    return await this.tasks.update(id, {      ...changes,      updatedAt: Date.now(),    })  }  /* 提醒相关方法 ...*/

    智能排序算法:未完成 > 有截止时间 > 创建时间

    自动过期检测:通过

    dueDate

    字段+定时器实现

    离线存储:IndexedDB + 本地备份机制

「典型查询示例」

// 获取24小时内到期的任务const upcomingTasks = await db.tasks  .where('dueDate')  .between(Date.now(), Date.now() + 86400000)  .toArray()


四、提醒系统(多窗口协同)

「架构设计」

export function useReminder() {  /**   * 检查是否有需要提醒的事项   */  async function checkReminders() {    const reminders = await db.checkReminders()    reminderQueue.value = reminders    if (reminderQueue.value.length > 0) {      window.ipcRenderer.send('show-reminder-window')    }  }

    主窗口:轮询检查

    提醒窗口:队列管理+动画效果

    IPC消息流:show-reminder-window / hide-reminder-window

「动效实现」

    <TransitionGroup name="reminder">      <div        v-for="reminder in reminderQueue"        :key="reminder.id"        class="relative bg-white rounded-2xl p-4 w-[180px] border border-gray-100 animate-slide-in before:content-[''] before:absolute before:bottom-[-8px] before:left-[30px] before:w-4 before:h-4 before:bg-white before:transform before:rotate-45"      >        <div class="flex justify-between items-start mb-2">          <h3 class="font-medium select-none">{{ reminder.title }}</h3>          <span            class="text-xs bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full ml-2"          >            {{              new Date(reminder.reminderTime).toLocaleTimeString([], {                hour: '2-digit',                minute: '2-digit',              })            }}          </span>        </div>        <p class="text-gray-600 text-sm mb-4 select-none">          {{ reminder.description || '&#8203;' }}        </p>        <button          @click="acknowledgeReminder(reminder)"          class="w-[60px] bg-blue-500 text-white py-1.5 rounded-full text-sm hover:bg-blue-600 transition-colors select-none"        >          知道了        </button>      </div>    </TransitionGroup>

使用Vue TransitionGroup + CSS Keyframe实现卡片弹出效果


五、性能优化实践

    「窗口管理」:子窗口单例模式(避免内存泄漏)

    「3D渲染」:离屏Canvas + 按需渲染

    「数据库」:批量操作+索引优化

    「打包优化」:electron-builder配置多平台构建

// @see - https://www.electron.build/configuration/configuration{  $schema: "https://raw.githubusercontent.com/electron-userland/electron-builder/master/packages/app-builder-lib/scheme.json",  appId: "YourAppID",  asar: true,  productName: "小桌宠",  directories: {    output: "release/${version}",  },  files: ["dist", "dist-electron"],  mac: {    target: ["dmg"],    artifactName: "${productName}-Mac-${version}-Installer.${ext}",  },  win: {    target: [      {        target: "nsis",        arch: ["x64"],      },    ],    artifactName: "${productName}-Windows-${version}-Setup.${ext}",  },  nsis: {    oneClick: false,    perMachine: false,    allowToChangeInstallationDirectory: true,    deleteAppDataOnUninstall: false,  },  linux: {    target: ["AppImage"],    artifactName: "${productName}-Linux-${version}.${ext}",  },}


结语:桌面应用的思考

通过这个项目验证了Electron在现代桌面开发中的可行性。尽管安装包体积较大,但开发效率和跨平台能力优势明显。未来计划加入:

    宠物更换系统 ✅

    更多交互功能

宠物更换功能已发布,文章地址:

https://juejin.cn/post/7475544117415624739

「顺便一提」:项目结合AI开发,省时又省力,一个字,爽!!!

关注更多AI编程资讯请去AI Coding专区:https://juejin.cn/aicoding

""~

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

桌面应用 Electron 3D宠物 任务管理 性能优化
相关文章