electron-updater实现electron全量更新和增量更新——渲染进程UI部分

news2025/1/16 0:51:25

同学们可以私信我加入学习群!


正文开始

  • 前言
  • 更新功能所有文章汇总
  • 一、两个同心球效果实现
  • 二、球内进度条、logo、粒子元素实现
    • 2.1 球内包含几个元素:
    • 2.2 随机粒子生成方法generateRandomPoint
    • 2.3 创建多个粒子的方法createParticle
  • 三、gsap创建路径动画,实现粒子动画
  • 总结


前言

更新功能的实现分为三篇文章来讲解:
1.主进程更新
2.开发调试技巧
3.渲染进程部分。

我在开发过程中,是先开发的主进程主要功能,再完善渲染进程部分的显示。因为当没有前端时,可以写几个简单的标签显示结果,保证主要功能基本完成,再完善前端交互。
效果图如下:
在这里插入图片描述
上面有几个简单的交互:

  • 打开软件时,页面向主进程通信,查询是否更新
  • 发现需要更新,弹出一个更新交互页面,页面显示更新信息和更新操作
  • 更新时,点击关闭按钮,会进入后台更新模式,登录进去后,点击左上角的更新标志,会弹出更新页面。

大的需求就是这样三个,至于细节后文再展开叙述,比如跳过版本如何实现,如何保障登录页和登录后,更新的进度是保持一致的……

更新功能所有文章汇总

  1. electron-updater实现electron全量更新和增量更新——主进程部分
  2. electron-updater实现electron全量更新和增量更新——注意事项/技巧汇总
  3. electron-updater实现electron全量更新和增量更新——渲染进程UI部分
  4. electron-updater实现electron全量更新和增量更新——渲染进程交互部分

一、两个同心球效果实现

在讲解前,我们先整体了解一下前端的文件结构:
在这里插入图片描述

  • updateprogress.vue是唯一的vue文件
  • updateBall.js:和中间的球相关的逻辑
  • updateHandle.js:操作按钮相关的逻辑
  • store/update.js:更新模块的全局变量

静态页面部分没什么好说的,就是一个遮罩加两个球,还有一些按钮,我的审美并不好,大家可以自行设计。球的立体效果就是靠阴影效果,代码如下:

<div
    :style="{ width: ballRadius * 2 + 'px', height: ballRadius * 2 + 'px' }"
    class="ball">
      
</div>

<style scope>
.ball {
  border-radius: 50%;
  //background: linear-gradient(135deg, #fff, #ddd);
  background-color: #fff;
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .1),
  0 0 10px 2px rgba(0, 0, 0, .1);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  flex-direction: column;
}

.ball::before {
  content: "";
  width: 80%;
  height: 80%;
  border-radius: 50%;
  //background: linear-gradient(315deg, #ddd, #fff);
  background-color: #fff;
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .1),
  0 0 10px 2px rgba(0, 0, 0, .1);
  position: absolute;
}
</style>

类ball是外层的大球,设置的半径ballRadius 为100,伪类:before是小球,大球小球靠阴影效果,塑造立体感。

二、球内进度条、logo、粒子元素实现

2.1 球内包含几个元素:

  • logo
  • 不规则的粒子
  • 进度条

外层的ball采用的flex布局,布局方向是纵向,所以logo通过图片标签直接引入,设置好宽高即可,下面依次写进度条、粒子等元素:

 <div :style="{width:ballRadius*2+'px',height:ballRadius*2+'px'}" class="ball">
      <img alt="Logo" class="logo" src="/public/img/log-opacity.png">
      <div style="display: flex;flex-direction: column;width: 60%">
        <Progress :percent="update_info.percent || 0" :stroke-width="5" style="flex-grow: 1;margin-right: 4px">
          <div style="width: 100%;display: flex;flex-direction: row;justify-content: center;align-content: center">
            <span>{{ update_info.percent || 0 }}%</span>
            <span style="color: #1a1a1a;margin-left: 8px">{{ update_info.speed || '0kb' }}</span>
          </div>
        </Progress>
      </div>
      <div class="particles">
        <!--        循环渲染粒子-->
        <div v-for="(particleItem,index) in particlesList"
             :key="index"
             :ref="el => setItemRef(index, el)"
             :style="{left: particleItem.left+'px',top:particleItem.top+'px',backgroundColor:particleItem.color}"
             class="particle">
        </div>
      </div>
    </div>

2.2 随机粒子生成方法generateRandomPoint

重点讲解一下上面的粒子渲染。

首先,粒子的容器是和最大的球重合的,所以采用absolute定位,css代码如下:

.particles {
  position: absolute;
  width: 100%;
  height: 100%;
}

粒子渲染最重要的是随机在圆环位置生成粒子的逻辑,这部分的算法核心其实就是初中数学知识:

  1. 外球半径(outRadius)-内球半径(radius)=圆环半径
  2. 圆环半径*随机数+内球半径(radius)=落在圆环内的随机半径
  3. 落在圆环内的随机半径*角度的cos和sin值,就分别是随机半径终点的坐标

转化为代码就是:

//生成radius外,outRadius内圆环上的坐标
      const randomRadius = radius + Math.random() * (outRadius - radius)
        const outX = randomRadius * Math.cos(angle)
        const outY = randomRadius * Math.sin(angle)

上面的代码就会生成angle角度方向,不同半径的坐标,如果angle角度也是随机的,那么就会生成圆环内随机散布的粒子

const angle = Math.random() * (2 * Math.PI)
      const randomRadius = radius + Math.random() * (outRadius - radius)
        const outX = randomRadius * Math.cos(angle)
        const outY = randomRadius * Math.sin(angle)

然后根据这个算法,我又增加了两种场景,一种是随机粒子是在内球半径上,得到粒子的坐标,思路是一样的,就不再赘述:

        //生成半径radius上的坐标

        const innerX = Math.random() * radius * Math.cos(angle)
        const innerY = Math.random() * radius * Math.sin(angle)

另一种是随机粒子是在内球半径内,也就是粒子随机散布在小球内:

       //生成半径radius内的坐标

        const innerX = Math.random() * radius * Math.cos(angle)
        const innerY = Math.random() * radius * Math.sin(angle)

最终这个方法就是:

 function generateRandomPoint(radius, outRadius) {
        //根据半径生成随机坐标,radiusArr:半径上的坐标,outRadiusArr:半径外的坐标,innerRadiusArr:半径内的坐标
        //outRadiusArr只有存在外环半径outRadius时才会生成
        // 生成一个0到2π之间的随机角度
        const angle = Math.random() * (2 * Math.PI)

        // 极坐标到笛卡尔坐标的转换,生成半径radius上的坐标
        const x = radius * Math.cos(angle)
        const y = radius * Math.sin(angle)
        //生成半径radius内的坐标

        const innerX = Math.random() * radius * Math.cos(angle)
        const innerY = Math.random() * radius * Math.sin(angle)

        //生成radius外,outRadius内的坐标
        // debugger
        const randomRadius = radius + Math.random() * (outRadius - radius)
        const outX = randomRadius * Math.cos(angle)
        const outY = randomRadius * Math.sin(angle)


        return {
            radiusArr: [x, y],
            innerRadiusArr: [innerX, innerY],
            outRadiusArr: [outX, outY]
        }
    }

本文的设计是将粒子散布在圆环内,所以只需要返回值的outRadiusArr参数即可。

2.3 创建多个粒子的方法createParticle

通过上面的generateRandomPoint方法,我们可以得到粒子的一个随机坐标。只要我们循环调用该方法,那就会循环得到粒子的不同坐标,代码如下:

    function createParticle(num) {
        // debugger
//  根据num生成随机粒子
        for (let i = 0; i < num; i++) {
            const {
                outRadiusArr: [outX, outY]
            } = generateRandomPoint(70, ballRadius.value)
            const particle = {
                color: getRandomRGBColor(),
                left: 100 + outX,
                top: 100 + outY,
            }
            particlesList.value.push(particle)
        }
    }

其中的getRandomRGBColor方法是获取随机颜色的方法:

    function getRandomRGBColor() {
        // 限制绿色和蓝色分量在100到255之间,红色分量在0到100之间
        const r = Math.floor(Math.random() * 101) // 0 to 100
        const g = Math.floor(Math.random() * 156) + 100 // 100 to 255
        const b = Math.floor(Math.random() * 156) + 100 // 100 to 255
        return `rgb(${r}, ${g}, ${b})`
    }

最终使用vue的v-for将粒子循环渲染到页面。

三、gsap创建路径动画,实现粒子动画

使用gsap插件,可以很方便地实现元素围绕某个路径运动。不仅限于圆弧,还可以是曲线、折线、不规则图形,gsap是flash基于js上的实现,功能十分强大,有兴趣的同学可以查看往期博文,这里不重点阐述概念。

创建动画的方法如下:

    function createAnimation(movementRange = 3) {
        // 使用GSAP创建动画
        particlesList.value.forEach((particle, index) => {
            // 使用GSAP创建动画
            gsap.to(particleRefs.value[index], {
                motionPath: {
                    path: '#svg',
                    align: '#svg',
                    alignOrigin: [Math.random() * 10 - 5, Math.random() * 10 - 5]
                },
                repeat: -1, // 无限重复
                duration: 3 * Math.random() + 2, // 随机持续时间

                ease: 'linear', // 线性运动
                delay: Math.random() * 2 // 随机延迟
            })
        })
    }

这里有几个小技巧:

  1. 仔细的同学可以发现,在vue中,粒子的ref变量是通过setItemRef方法实现的
	//vue中的代码
        <div v-for="(particleItem,index) in particlesList"
             :key="index"
             :ref="el => setItemRef(index, el)"
             :style="{left: particleItem.left+'px',top:particleItem.top+'px',backgroundColor:particleItem.color}"
             class="particle">
        </div>

	//对应的js代码     
    function setItemRef(index, el) {
        if (el) {
            // 如果元素存在,则将其存储在对象中
            particleRefs.value[index] = el
        } else {
            // 如果元素不存在(可能是被销毁了),则从对象中删除
            delete particleRefs.value[index]
        }
    }

这个方法最终会得到一个保存粒子ref对象的数组particleRefs。

  1. gsap动画需要指定动画元素, gsap.to的第一个参数particleRefs.value[index]就是循环得到的动画元素,也就是每一个粒子。
  2. gsap的基础配置十分简单,这里主要是讲解motionPath参数。这是路径插件的参数:
   motionPath: {
                    path: '#svg',
                    align: '#svg',
                    alignOrigin: [Math.random() * 10 - 5, Math.random() * 10 - 5]
                },

前面两个参数好理解,就是粒子绕着路径运动,总得先定义路径,svg就是路径的id。alignOrigin是粒子偏移路径的距离,使用随机数,可以让粒子运动效果有杂乱随机的感觉。
4. svg是路径path的id,不是svg标签的id,这个要注意,对应的svg代码如下:

  <!-- SVG 圆形元素 -->
      <svg style="position: absolute" height="95%" viewBox="-160 -160 320 320" width="95%"
           xmlns="http://www.w3.org/2000/svg">
        <path id="svg"
              d="M 0 160
         A 160 160 0 0 1 0 -160
         A 160 160 0 0 1 0 160 Z"
              fill="transparent" stroke="none"/>
      </svg>

构建svg的时候,还要注意原点、是否闭合、起止点等信息,也就是d元素中的数据。如果d属性的路径设置不合理,可能会造成path路径与外部的圆不重合的问题。当然这些一般没人去手输,通过Adobe AI软件、在线svg绘制网站、ai助手等,都可以得到符合要求的svg路径。

对svg不熟悉的同学,要关注viewBox属性,这是svg可以跟随父级容器按照比例增大缩小的关键。

  1. 启动动画:当用户点击立即更新时,需要做三件事:1)创建200个粒子;2)启动动画;3)检查更新。代码如下:
    function startUpdate() {
        createParticle(200)
        setTimeout(() => {
            createAnimation()
            myApi.handlePcToUpdate()
        }, 100)

    }

总结

本文主要是讲解了更新模块的页面样式实现,下一篇文章讲解页面上的交互逻辑实现。

大家如果需要联系博主,或者获取博主各系列文章对应的资源,可以通过中二少年学编程的个人主页来获取。

有任何前端项目、demo、教程需求,都可以联系博主,博主会视精力更新,免费的羊毛,不薅白不薅!~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1968236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于python的百度迁徙迁入、迁出数据分析(六)

书接上回&#xff0c;苏州市我选取了2024年5月1日——5月5日迁入、迁出城市前20名并求了均值&#xff0c;从数据中可以看出苏州市与上海市的关系还是很铁的&#xff0c;都互为对方的迁入、迁出的首选且迁徙比例也接近4分之一&#xff0c;名副其实的老铁了&#xff1b; 迁出城市…

Seurat-SCTransform与harmony整合学习续(亚群分析)

目录 提取细胞亚群 SCTransform-harmony技术路线 ①亚群SCTransform标准化 ②harmony去批次 这里对上一章的内容进行补充&#xff1a; Seurat-SCTransform与harmony整合学习-CSDN博客 提取细胞亚群 rm(list ls()) library(Seurat)#好像先后需要先后加载 library(patchw…

【Jenkins】在linux上通过Jenkins编译gitee项目

因项目需求近期在linux服务器上部署了Jenkins来自动编译gitee上的项目源码&#xff0c;期间踩到了一些坑&#xff0c;花费了不少时间来处理&#xff0c;特此记录。 所需资源下载列表&#xff1a; Jenkins &#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.46…

文件系统 --- 重定向,缓冲区

序言 本篇文章的内容和上一篇文章 &#x1f449;点击查看 紧密相连&#xff0c;所以为了更好的理解本篇文章&#xff0c;需要大家将前置知识准备好哦&#x1f607;。  本文主要向大家介绍文件的重定向&#xff0c;以及基于用户级别的缓冲区和基于操作系统级别的缓冲区。原来看…

AI技术和大模型对人才市场的影响

012024 AI技术和大模型 2024年AI技术和大模型呈现出多元化和深入融合的趋势&#xff0c;以下是一些关键的技术方向和特点&#xff1a; 1. 生成式AI 生成式AI&#xff08;Generative AI&#xff09;在2024年继续快速发展&#xff0c;它能够创造全新的内容&#xff0c;而不仅仅…

Redis——有序集合

目录 1. 添加元素 ZADD 2. 查看全部元素 ZRANGE 3. 查看某个元素的分数 ZSCORE 4. 查看元素的排名 ZRANK SortedSet 也叫 ZSet ,即有序集合&#xff0c; 有序集合与集合的区别&#xff1a; 有序集合的每个元素都会关联一个浮点类型的分数&#xff0c;依赖该分数的的大小对…

《Milvus Cloud向量数据库指南》——多模态融合新纪元:音频、视频与文本的无缝转换

在探讨多模态数据处理与应用的广阔领域中,多模态文本、音频、视频数据的融合与交互成为了近年来人工智能研究的热点之一。这一趋势不仅推动了技术的深度发展,也为众多行业带来了前所未有的创新机遇。本文将深入剖析多模态文本-音频与多模态文本-视频RAG(Retrieval-Augmented…

书生大模型基础岛-第三关:LangGPT结构化提示词编写实践

1.来源和任务 来源&#xff1a; https://github.com/InternLM/Tutorial/blob/camp3/docs/L1/Prompt/task.md 任务&#xff1a; 背景问题&#xff1a;近期相关研究发现&#xff0c;LLM在对比浮点数字时表现不佳&#xff0c;经验证&#xff0c;internlm2-chat-1.8b (internlm2-…

C++——list容器以及手动实现

LIST容器 list概述列表容器属性例子 list函数构造函数默认构造函数&#xff1a;带有元素个数和元素初值的构造函数&#xff1a;范围构造函数&#xff1a;拷贝构造函数&#xff1a;移动构造函数&#xff1a;示例 赋值运算符重载拷贝赋值操作符 (1)&#xff1a;移动赋值操作符 (2…

安全通信|数据加密的由来|加密算法简介|中间人攻击与证书认证|身份验证

&#x1f448;️下一篇 计算机网络-专栏&#x1f448;️ 数据加密的由来|加密算法简介|中间人攻击与证书认证 引言 在客户端(client)-服务器(server)模式下&#xff0c;客户端与服务器间通信&#xff0c;如果明文传输数据&#xff0c;在传输过程被劫持&#xff0c;内容直接泄…

MySQL触发器和存储过程

1、触发器 &#xff08;1&#xff09;&#xff1a;建立触发器&#xff0c;订单表中增加订单数量后&#xff0c;商品表商品数量同步减少对应的商品订单出数量,并测试 mysql> create trigger orders_after_insert_trigger-> after insert on orders for each row-> up…

不知道你们有没有我这样的一种状态...总是这样又总是那样...

各位小伙伴们&#xff0c;我是风尚&#xff0c;我不知道你们有没有那么一刻&#xff0c;就是感觉站在人生的十字路口&#xff0c;感觉自己就像是被扔进了一个没有导航的迷宫&#xff0c;四周都是墙&#xff0c;头顶是蓝天白云&#xff0c;却怎么也找不到出口的方向&#xff1f;…

重磅推荐!GBD再度登顶Lancet!| GBD数据库周报(7.17~7.23)

全球疾病负担&#xff08;GBD&#xff09;是迄今为止规模最大、最全面的一项研究&#xff0c;旨在量化不同地区和不同时期的健康损失&#xff0c;从而改善卫生系统并消除差异。 该研究由华盛顿大学健康指标与评估研究所 (IHME) 牵头&#xff0c;是一项真正的全球性研究&#xf…

MySQL--数据库与表的操作

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 数据库的基本操作 # 1、查看数据库show databases;​# 2、创建数据库create database 数据库名称;​# 3、删除数据库drop databse 数据库名称; 数据表…

RAC(Teamcenter )开发,Bom行解包和打包的方法

1、打包 UnpackAllAction allAction new UnpackAllAction((AbstractBOMLineViewerApplication) currentApplication, "packAllAction"); new Thread(allAction).start();2、解包 UnpackCommand command new UnpackCommand(bomLine); command.executeModal();3、注…

Marin说PCB之Orcad Capture调网表时出现了“Duplicate Pin Name”该怎么搞?

最近大巴黎在如火如荼的举行着奥运会&#xff0c;中国健儿们也是不负众望在很多项目中取得金牌的好成绩&#xff0c;其中中国选手陈芋汐/全红婵夺得巴黎奥运会跳水女子双人10米台金牌&#xff0c;其实没有看我就知道比赛的结果了&#xff0c;肯定是我们中国队夺得金牌的。 看到…

月薪竟然高达60k,AI大模型凭什么?

你是不是最近经常看到或听到“AI大模型”这个关键词&#xff1f;我也是&#xff01;所以好奇去Boss直聘上搜了下工作机会。看到结果时&#xff0c;我有点不淡定了&#xff01;薪资竟然这么高&#xff01; 这是我随便搜的结果&#xff0c;发出来给大家看看。 下面&#xff0c;我…

多线程习题

1.使用两个线程完成两个文件的拷贝&#xff0c;分支线程1拷贝前一半&#xff0c;分支线程拷贝后一般&#xff0c;主线程回收两个分支线程的资源 #include<myhead.h> struct Buf {const char *srcfile;const char *destfile;int start;int len1; }; //创建求源文件大小的函…

【C#】.net core 6.0 webapi 使用core版本的NPOI的Excel读取数据以及保存数据

欢迎来到《小5讲堂》 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景读取并保存NPOI信息NPOI 插件介绍基本功能示例代码写入 Excel 文件…