当春节前不想写业务的前端会做什么(二)

背景

今天已经初六了,想必各位大佬跟我一样也即将踏上工作的路途了。小弟在这里祝愿各位大佬在新的一年,技术进步,事业有成,财源滚滚。


书接上文,过年前在公司由于不想写业务而做了一个小demo(不了解的大佬可以看一下上次都做了什么当春节前不想写业务的前端会做什么 - 掘金 (juejin.cn)),但是上次完成的仅仅是个小玩具甚至他都不怎么好玩,这次我们来继续深入完成更多有意思的功能。 以下是Momo的简单介绍:

  • 名称: Momo
  • 性别: 不详
  • 情绪: 默认/生气
  • 状态: Loading/working
  • 自述: 大家好我是Momo,诞生于2024年,我是一名智能桌面助手哦。

Momo生活照

完善页面

添加阴影

由于2d的桌宠看起来像一张图片没那么多立体感,这里决定加一个阴影。

html 复制代码
<style>
.toyarMomo {
    ...
    box-shadow: 9px 6px 16px 3px rgba(0, 0, 0, 0.2);
    ...
}
</style>

增加耳朵亮闪闪效果

html 复制代码
<style>
    .momo-left_Ear::before,
    .momo-right_Ear::before {
      content: "";
      position: absolute;
      inset: 0;
      background: url('./src/star.awebp');
      border-radius: 44% 49% 22% 65% / 100% 100% 0% 0%;
      /* mix-blend-mode: color-dodge; */
      /* mix-blend-mode: hard-light; */
      /* mix-blend-mode: multiply; */
      mix-blend-mode: difference;
    }
</style>

效果: 解释一下 这里使用了一张gif动图就是下面这个星星闪闪的图片,并且作为耳朵的伪元素背景,最后使用css,mix-blend-mode: difference;

这个css的意思是该元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。不了解的可以查看这个链接学习mix-blend-mode - CSS:层叠样式表 | MDN (mozilla.org)

ps:我倒是没觉得很好看,不过炫酷就完了

脸部反射光

上面也提到过我觉得2d不够立体,这里再加一个面部灯光反射

html 复制代码
<style>
    .momoBody::after {
      content: "";
      position: absolute;
      inset: 0;
      border-radius: 55% 45% 77% 23% / 54% 22% 78% 46%;
      background: linear-gradient(90deg,
          transparent 0%,
          rgba(255, 255, 255, 0.05) var(--per),
          rgba(255, 255, 255, 0.1) var(--per),
          rgba(255, 255, 255, 0.3) calc(var(--per) + 15%),
          rgba(255, 255, 255, .1) calc(var(--per) + 30%),
          rgba(255, 255, 255, 0.05) var(--per),

          transparent 100%);
      mix-blend-mode: color-dodge;
      z-index: 999;
    }
</style>
<script>
setInterval(() => {
  if (flag) {
    data += 1
  } else {
    data -= 1
  }
  if (data === 30 || data === -50) {
    flag = !flag
  }
  this.body.style.setProperty('--per', data + '%')
}, 30)
</script>

效果:

解释一下,这里使用了一个线性渐变背景作为伪元素的背景,然后线性渐变是一个透明到白色再到透明的效果,然后定时器修改css属性改变这里渐变的位置

为什么不用animation?,当时想着做别的东西来着,后来写完了懒得改了,不过这个也挺机械的感觉不太好(后面优化吧)

使用Electron

介绍

众所周知,htmlcssjs 通常只能运行再浏览器中,但是作为一个桌宠只能运行在浏览器中是不是有点说不太过去,所以这里使用Electron。

安装

  1. 首先得有node环境这里不演示了

  2. 初始化package.json npm init -y

  3. 安装electron

    npm install electron --save-dev

    注意这里npm安装electron 可能会失败,大概是镜像原因,解决方案 npm安装Electron 项目失败报错问题和解决办法_npm install electron报错-CSDN博客

  4. 安装forge npm install --save-dev @electron-forge/cli

    执行 npx electron-forge import

    安装后的项目结构

创建窗口与加载页面

  1. 创建main.js 并修改package.json中入口js名称
  2. 创建一个html文件
  3. 在main.js中创建窗口文件

运行 npm run start 查看代码是否生效 看到窗口证明可以了

最后将写的html 代码移植过来然后在npm run start 看一下,可以看到这里也运行起来了

窗口配置

前面虽然能运行但是白色的边框根本不像桌宠而且这里鼠标事件也不能穿透,这里需要一些配置

可以看到这里已经十分接近桌宠了,但是有个致命问题,就是要么鼠标事件穿透不过去,要么就是能穿透但是点击不了桌宠了,这样也没法交互了

效果

使用ipc通信解决鼠标事件问题

解释一下,这里当鼠标移入桌宠时候则开始鼠标事件监听触发,当鼠标移出桌宠时候则关闭鼠标事件监听触发。

ipc通信这里就不解释了

桌宠的交互功能(1)

html 复制代码
<style>
    .controller {
      position: absolute;
      top: 50%;
      left: 50%;
      width: calc(var(--size) * 8/15);
      height: calc(var(--size) * 8/15);
      transform: translate(-50%, -50%);
      z-index: -10;
      transition: all 2s;
    }

    .ctlItem {
      position: absolute;
      width: calc(var(--size) * 8/15);
      height: calc(var(--size) * 8/15);
      z-index: 1;
      transition: transform 2s;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 0 6px rgba(255, 255, 255, 0.2);
      background-color: rgba(255, 255, 255, 0.4);
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .ctlItem>.empty {
      background-image: url('./src/asstes/add.svg');
      background-size: 100% 100%;
    }
    .ctlItem>.ctlItem_close{
      width: calc(var(--size) * 2/15);
      height: calc(var(--size) * 2/15);
      position: absolute;
      /* right: calc(var(--size) * -1/15);
      top: calc(var(--size) * -1/15); */
      top: calc(var(--size) * 1/15);
      right: calc(var(--size) * 1/15);
      background-image: url('./src/asstes/close.svg');

      background-size: 100% 100% !important;
    }
    .ctlItem>.ctlItem_close:hover{
      background-image: url('./src/asstes/closeHover.svg');
    }

    .controller.active>.ctlItem {
      transform: rotate(calc(var(--ctlItem) + 0deg)) translate(0px, calc(var(--size) * -5/3));
    }

    .controller.active>.ctlItem>div {
      transform: rotate(calc(var(--ctlItem) * -1deg));
    }

    .ctlItem>div {
      width: calc(var(--size) * 5/15);
      height: calc(var(--size) * 5/15);
      background-size: 100% 100% !important;
    }

    .ctlItem:hover {
      box-shadow: 0 0 6px rgba(255, 255, 255, 0.2);
      background-color: rgba(255, 255, 255, 0.7);
      cursor: pointer;
    }
</style>
<script>
 class toyarMomo {
     ...
     createBtn(item, i) {
        const ctlItem = document.createElement('div');
        const head = 'momo_'
        ctlItem.className = 'ctlItem'
        ctlItem.style.setProperty('--ctlItem', item + 'deg')


        const {path,imgURL} = JSON.parse(localStorage.getItem(head + i)) ||{
          path:'',
          imgURL:""
        }
        const src = path || 'empty'
        if (src === 'empty') {
          ctlItem.innerHTML = `<div class="empty" > </div>`
          ctlItem.setAttribute('fileUrl', '')
        } else {
          ctlItem.innerHTML = `
            <div style="background:url(${imgURL})"> </div>
            `
            this.createCloseBtn(ctlItem,i)
            // <div class="ctlItem_close" onClick="closectlItem(${i})"></div>
          ctlItem.setAttribute('fileUrl', src)
        }
        ctlItem.addEventListener('click', async () => {

          if (window.versions) {
            if (ctlItem.getAttribute('fileUrl')) {
              window.versions.ctlItemClick({
                type: ctlItem.getAttribute('fileUrl'),
                index: i
              })
              return
            }

            let {path,imgURL} = await window.versions.ctlItemClick({
              type: 'empty',
              index: i
            })
            localStorage.setItem(head + i, JSON.stringify({
              path,
              imgURL
            }))
            ctlItem.setAttribute('fileUrl', path)
            ctlItem.innerHTML = `
                <div 
                  style="
                    background:url(${imgURL})"
                  >
                </div>
                `
            this.createCloseBtn(ctlItem,i)
                // <div class="ctlItem_close">x</div>
          }
        })
        return ctlItem
      }
     createController(max = 8) {
        const controller = document.createElement('div');
        this.controller = controller
        controller.className = 'controller'

        let route = 360 / max
        for (let i = 0; i < max; i++) {
          controller.append(this.createBtn(i * route, i))
        }
        return controller
      }
     createRoot() {
         ...
         main.addEventListener('dblclick', () => {
          this.controller.classList.toggle('active')
        })
        const controller = this.createController()
        main.append(controller)
         ...
     }

 }
</script>
html 复制代码
<script>
    //主进程
 ipcMain.handle('ctlItemClick',async (event,{type,index})=>{
    if(type === 'empty'){
      const {filePaths} = await dialog.showOpenDialog({
        properties: ['openFile'],
        buttonLabel:'选择',
        title:'快捷方式',
        filters:[
          {'name':'应用',extensions:['exe']},
          {'name':'图片文件',extensions:['ico','png','jpg','jpeg','svg']},
          // {'name':'媒体文件',extensions:['avi','mp4','mp3']},
        ]
    })
    const fileIcon = await  app.getFileIcon(filePaths[0]);
    let imgURL= fileIcon.toDataURL()
    console.log(imgURL);
    return {imgURL,path:filePaths}
    }else{
      shell.openPath(type)
    }
  })
</script>

双击效果

添加删除与启动应用效果

相关推荐
勿语&24 分钟前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
黄尚圈圈26 分钟前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水1 小时前
简洁之道 - React Hook Form
前端
正小安3 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光5 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   5 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   5 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web5 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常5 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式