Electron 实现切换暗_亮模式与主题

2023-10-29

QQ20230105-180050-HD.gif

文章末尾附上仓库地址!!!!

清单

初始化工程

使用 electron-vite 作为模板,方便大家尽快吧项目跑起来

# 创建模板
npm create electron-vite
# 进入目录
cd electron-vite-vue

# 下载依赖,如果有异常的话可以尝试 cnpm 
cnpm i

# 目前这个模板缺少了 esbuild 依赖,所以需要补上
cnpm i esbuild -D 

# 启动项目
npm run dev

出现这个页面,初始化工程部分就结束了

image.png

ElementPlus 引入

cnpm i element-plus

main.ts 全局引入 ElementPlus

修改 src/main.ts

import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
// ElementPlus 引入
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";

const app = createApp(App);
// ElementPlus 注册
app.use(ElementPlus);
app.mount("#app").$nextTick(() => {
  postMessage({ payload: "removeLoading" }, "*");
});

启动项目如果报以上错误的话,将缺的两个包下载就好了
image.png

cnpm i @vue/shared @vue/reactivity

测试组件引用

修改 src/App.vue 测试一下组件引用, 务必清空src/style.css哈

<template>
  <el-container>
    <el-header class="header">Header</el-header>
    <el-container>
      <el-aside width="200px" class="aside">Aside</el-aside>
      <el-container>
        <el-main class="main">Main</el-main>
        <el-footer class="footer">Footer</el-footer>
      </el-container>
    </el-container>
  </el-container>
  <el-row class="mb-4">
    <el-button>Default</el-button>
    <el-button type="primary">Primary</el-button>
    <el-button type="success">Success</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </el-row>
  <el-row>
    <el-col :sm="12" :lg="6">
      <el-result
        icon="success"
        title="Success Tip"
        sub-title="Please follow the instructions"
        >
        <template #extra>
          <el-button type="primary">Back</el-button>
        </template>
        </el-result>
          </el-col>
          <el-col :sm="12" :lg="6">
          <el-result
          icon="warning"
          title="Warning Tip"
          sub-title="Please follow the instructions"
            >
            <template #extra>
            <el-button type="primary">Back</el-button>
            </template>
            </el-result>
            </el-col>
            <el-col :sm="12" :lg="6">
            <el-result
          icon="error"
          title="Error Tip"
          sub-title="Please follow the instructions"
            >
            <template #extra>
            <el-button type="primary">Back</el-button>
            </template>
            </el-result>
            </el-col>
            <el-col :sm="12" :lg="6">
            <el-result icon="info" title="Info Tip">
            <template #sub-title>
            <p>Using slot as subtitle</p>
            </template>
            <template #extra>
            <el-button type="primary">Back</el-button>
            </template>
            </el-result>
            </el-col>
            </el-row>
            </template>

            <script setup lang="ts"></script>

<style>
  .header {
    background: var(--el-color-primary);
  }
  .aside {
    background: var(--el-bg-color-page);
  }
  .main {
    background: var(--el-bg-color);
  }
  .footer {
    background: var(--el-bg-color-page);
  }
</style>

image.png

ElementPlus暗黑模式

官方文档传送门

  • ElementPlus的暗黑模式 切换方式是在 html元素属性上 增删 class=“dark”
  • 暗黑模式需要在man.ts 文件引入
  • 可以通过 useDark | VueUse 切换暗黑模式

引用element-plus暗黑主题样式

修改 src/main.ts

//.......
// 增加暗黑模式样式文件
import 'element-plus/theme-chalk/dark/css-vars.css'
//.......

使用useColorMode

官方文档传送门

具有自动数据持久化的主题模式hooks(深色/浅色/自定义)。

  • 将颜色模式存在本地存储中持久化
  • 颜色模式为相应式属性
cnpm i @vueuse/core

修改 src/App.vue 改造增加模式切换部分

<template>
  <div style="margin-top: 20px">
    <el-radio-group v-model="mode" size="small">
      <el-radio-button label="light">浅色</el-radio-button>
      <el-radio-button label="dark">暗黑</el-radio-button>
      <el-radio-button label="auto">跟随系统</el-radio-button>
    </el-radio-group>
  </div>
<!--   ......... -->
</template>
<script setup lang="ts">
import { useColorMode } from "@vueuse/core";
import { onBeforeMount } from "vue";
const mode = useColorMode({
  // 如果模式为auto也需要回显回auto
  emitAuto: true,
  // 默认模式先默认auto,后续通过Electorn拿到当前App主题
  initialValue: "auto",
});
</script>

QQ20230105-162711-HD.gif

Electron暗黑主题同步

细心的小伙伴可能发现了,在改变暗黑模式时,顶部的窗口颜色并没有同步,只有在auto模式下才同步。这是因为顶部的窗口是原生窗口,我们只是改变了webpage 也就是我们特指“html” 部分的主题颜色,下面我们就像两部分联动起来。

IPC(进程间通信)

  • ipcMain模块用于从主进程(main process)异步通信到renderer进程。
  • ipcRenderer模块用于从一个renderer进程异步传送到主进程。

这里本章不做过多介绍,可以先简单理解为发布订阅,后续会更新此系列文章。

改造主线程

修改 electron/main/index.ts 增加两个主线程监听,放在文件末尾即可

// 获取APP当前主题模式
ipcMain.handle("dark-mode", () => {
  return nativeTheme.themeSource;
});
// 设置APP主题模式
ipcMain.handle("dark-mode:change", (_, type: "system" | "light" | "dark") => {
  nativeTheme.themeSource = type;
  return nativeTheme.themeSource;
});

改造

修改 src/App.vue 页面挂载时获取APP 的主题,同步到主题中

<script setup lang="ts">
  import { useColorMode } from "@vueuse/core";
  import { ipcRenderer } from "electron";
  import { onBeforeMount } from "vue";
  const mode = useColorMode({
    emitAuto: true,
    initialValue: "auto",
  });
  // 监听 Mode 改变
  const changeModel = (mode: "light" | "dark" | "auto") => {
    // Electorn的主题模式 auto 为 system 所以需要转换
    ipcRenderer.invoke("dark-mode:change", mode === "auto" ? "system" : mode);
  };
  onBeforeMount(() => {
    // 通过 ipcRenderer 与主线程通信
    // 获取到App主题 同步到 useColorMode 中
    ipcRenderer.invoke("dark-mode").then((type: "light" | "dark" | "system") => {
      mode.value = type == "system" ? "auto" : type;
    });
  });
</script>

QQ20230105-172532-HD.gif

主题切换

因为 ElementPlus 的主题可以通过css变量控制,如下面这个图一样。
image.png

useElementPlusTheme

useElementPlusTheme仓库地址

这个hooks没有找到原作者的博客地址以及文档,但是找到了仓库地址。为了代码可控性以及维护性,直接在文件中创建useElementPlusTheme 而不是下载。

增加文件 src/hooks/useElementPlusTheme.ts

import { onBeforeMount } from "vue";

/** 变量前缀 */
const PRE = "--el-color-primary";
const PRE_LIGHT = `${PRE}-light`;
const PRE_DARK = `${PRE}-dark`;
/** 白色 */
const WHITE = "#ffffff";
/** 黑色 */
const BLACK = "#000000";

const html = document.documentElement;

/**
 * 混合颜色
 */
const mix = (color1: string, color2: string, weight: number) => {
  weight = Math.max(Math.min(Number(weight), 1), 0);
  const r1 = parseInt(color1.substring(1, 3), 16);
  const g1 = parseInt(color1.substring(3, 5), 16);
  const b1 = parseInt(color1.substring(5, 7), 16);
  const r2 = parseInt(color2.substring(1, 3), 16);
  const g2 = parseInt(color2.substring(3, 5), 16);
  const b2 = parseInt(color2.substring(5, 7), 16);
  const r = Math.round(r1 * (1 - weight) + r2 * weight);
  const g = Math.round(g1 * (1 - weight) + g2 * weight);
  const b = Math.round(b1 * (1 - weight) + b2 * weight);
  const _r = ("0" + (r || 0).toString(16)).slice(-2);
  const _g = ("0" + (g || 0).toString(16)).slice(-2);
  const _b = ("0" + (b || 0).toString(16)).slice(-2);
  return "#" + _r + _g + _b;
};

/**
 * 更换颜色的方法
 * @param color 颜色
 */
const changeTheme = (color?: string) => {
  if (!color) return;
  // 设置主要颜色
  html.style.setProperty(PRE, color);
  // 循环设置次级颜色
  for (let i = 1; i < 10; i += 1) {
    html.style.setProperty(`${PRE_LIGHT}-${i}`, mix(color, WHITE, i * 0.1));
  }
  // 设置主要暗色
  const dark = mix(color, BLACK, 0.2);
  html.style.setProperty(`${PRE_DARK}-2`, dark);
};

export function useElementPlusTheme(color?: string) {
  onBeforeMount(() => changeTheme(color));
  return {
    changeTheme,
  };
}

使用 useElementPlusTheme

修改 src/App.vue

<template>
<!--  ......  -->
  <div>主题颜色: <el-color-picker v-model="themeColor" @change="changeTheme"/></div>
<!--  ......  -->
</template>
<script setup lang="ts">
import { useElementPlusTheme } from "./hooks/useElementPlusTheme";
// ......
const themeColor = ref("#cc312c");
const { changeTheme } = useElementPlusTheme(themeColor.value);
</script>

QQ20230105-175803-HD.gif

GitHub仓库地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Electron 实现切换暗_亮模式与主题 的相关文章

随机推荐

  • C++学习(二十八)值传递的性能问题

    对于int 直接传值比传引用节省了一次解引用的开销 其效率当然会高 基本数据类型都是优化过的 引用传值有两个好处 1 参数可以带回来值 2 大对象无需拷贝进去 对于大对象而言引用传递效率会更高
  • 线性代数的本质(干货!)

    原文链接 https www cnblogs com TenosDoIt p 3214096 html 从大学开始接触矩阵论和线性代数 记了很多公式 但是总感觉徘徊在线性代数的门外没有进去 感觉并没有接触到它的核心概念 不巧看到了这篇博客
  • 7.Unity中c#代码学习(物理系统刚体+碰撞检测(爆炸效果实现))

    刚体 通过添加组件Physics Rigidbody 实现对物体插入物理引擎 刚体 碰撞体 查看碰撞体范围 可以编辑碰撞的范围 碰撞体 在文件中创建物理材质 右键 create Pythsics material friction摩擦力 有
  • 建站平台(WebPlus)申请建站流程图及相关使用文献

    WebPlus系统是学校信息网络中心提供的用于建设部门网站的管理平台 可实现快速建站和校内信息资源共享平台 每个独立部门原则上只能申请一个WebPlus建站空间 平台使用方法请访问 http service webplus net cn 上
  • (转)CASE WHEN 用法

    Case具有两种格式 简单Case函数和Case搜索函数 简单Case函数 CASE sex WHEN 1 THEN 男 WHEN 2 THEN 女 ELSE 其他 END Case搜索函数 CASE WHEN sex 1 THEN 男 W
  • vue脚手架搭建、介绍和初始页面的构造(图文详细)

    文章目录 什么是vue脚手架 前置环境的安装 配置node js 安装脚手架vue cli 创建项目 项目配置 项目结构 修改初始页面 样式的less语法 什么是vue脚手架 Vue脚手架 Vue CLI 是一个官方提供的命令行工具 用于快
  • 【文件上传】绕过总结

    一般绕过会分为黑名单绕过 白名单绕过 特殊类型绕过 以下为文件上传后缀绕过 黑名单绕过 1 大小写绕过 eg a JSP a Jsp a jsP a jSP等等 2 空格绕过 一般保存文件名前后带空格 保存时都会被忽略掉 而php在传输中
  • linux_fasync的总结

    fasync的总结 我们知道 驱动程序运行在内核空间中 应用程序运行在用户空间中 两者是不能直接通信的 但在实际应用中 在设备已经准备好的时 候 我们希望通知用户程序设备已经ok 用户程序可以读取了 这样应用程序就不需要一直查询该设备 的状
  • window系统配置PCL的简化方法(不需要复制一百多个依赖项目名称,直接导入配置表)

    1 下载文件 百度网盘 链接 https pan baidu com s 1WQQ8kaDilaagjoK5IrYZzA 提取码 1111 注意 直接解压在E盘 不解压在E盘也可以 后续替换环境变量和属性表文件内的地址就行 props文件
  • 【独家发布】行业深度报告:《风口上的半导体

    作为关乎国民经济和国家安全的战略型行业 半导体行业在我国占据重要地位 尤其在美国对我国半导体核心产品和零部件实行技术封锁的大背景下 国产芯片亟需实现独立自主并获得长足发展 一场全产业链国产化替代风潮正愈演愈烈 与此同时 半导体行业也收获了诸
  • 使用Python,OpenCV的Meanshift 和 Camshift 算法来查找和跟踪视频中的对象

    使用Python OpenCV的Meanshift 和 Camshift 算法来查找和跟踪视频中的对象 1 效果图 2 源码 2 1 MeanShift 2 2 Camshift Continuously Adaptive Meanshif
  • vs2019登录提示“我们无法刷新此账户的凭证”

    打开代理服务器设置 查看自动设置代理与手动设置代理的开关有没有被自动打开 如果有的话把它关掉 就能正常登录了
  • D - 整数变换问题

    整数变换问题 题意 问我们最少经过多少次变换可以将n转化为m 题解 这个题我们很容易想到就是用dfs 但是数据范围也很明显不能用直接的暴力 所以我们需要剪枝 我们假设用最原始的暴力 就是每次循环两种情况一直到最后 这样的暴力很机械 很盲目
  • 华为OD机试真题-选修课-2023年OD统一考试(B卷)

    题目描述 现有两门选修课 每门选修课都有一部分学生选修 每个学生都有选修课的成绩 需要你找出同时选修了两门选修课的学生 先按照班级进行划分 班级编号小的先输出 每个班级按照两门选修课成绩和的降序排序 成绩相同时按照学生的学号升序排序 输入描
  • 百度地图,如何成为智能化位置服务平台

    深几度 产业数字化 撰稿 吴俊宇 编辑 吴俊宇 审阅 梁欣婷 摘要 对行业而言 百度地图在当下的角色转变具备代表性意义 这是产业数字化浪潮下的一次成功转型 在过去移动生态下诞生的产品 在今天都值得深入挖掘其中的数据价值 这些价值可以延展至国
  • 安卓期末大作业-图书馆借书系统、图书借阅app(附下载链接)

    安卓期末大作业 图书馆借书系统 借书APP 可以注册登录 保存数据记录 含源码和导出app 运行截图 安卓期末大作业 图书借阅APP 老师给了95分 可以注册登录 借阅书籍 还书 含数据库存储借书记录 导入AndroidStudio即可使用
  • 信标链:以太坊2.0的新起点

    原创 市后诸葛 虽然以太坊2 0依旧用 以太坊 命名 但以太坊1 0和以太坊2 0其实是完全不同的两种架构 以太坊1 0和2 0的差别 远不是POW和POS的区别 在以太坊2 0里面 基础链就是 信标链 在真正的以太坊2 0里面 是只有po
  • @With,@Accessors(chanins=true),@ExtensionMethod——Lombok常用注解

    目录 一 With 很少用 二 Accessors 非常好用 一 fluent 布尔型 二 chain 布尔型 三 ExtensionMethod 实验阶段 一 With 很少用 这个注解可以用在类上也可以用在单个的成员变量上 使lombo
  • C++中的指针概念梳理

    在C 中指针通常难以理解 即使是有经验的程序员也常常因为调试指针引发的错误而备受折磨 笔者在学习C 时常常被指针弄得晕头转向 于是决定对指针的概念做一次梳理 希望本文能够对C 入门者有些许作用 1 指针的概念 指针 pointer 是 指向
  • Electron 实现切换暗_亮模式与主题

    文章末尾附上仓库地址 清单 模板基于 electron vite vue vue3 ts vite 组件库 element plus hooks库 vueuse useElementPlusTheme 初始化工程 使用 electron v