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

背景

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


书接上文,过年前在公司由于不想写业务而做了一个小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>

双击效果

添加删除与启动应用效果

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui