修改主进程:main.js
// main.js
const { app, BrowserWindow } = require("electron");
const path = require("node:path");
const createWindow = () => {
try {
const mainWindow = new BrowserWindow({
width: 1200,
height: 870,
alwaysOnTop: true,
frame: false,
icon: path.join(__dirname, "./img/icon.ico"),
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
mainWindow.loadFile(path.join(__dirname, "index.html"));
// 打开开发工具
mainWindow.webContents.openDevTools();
} catch (e) {
console.error("Failed to create window:", e);
}
};
app.whenReady().then(() => {
createWindow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
// 在 Windows 和 Linux 上,关闭所有窗口时应该退出应用
app.on("window-all-closed", () => {
if (process.platform !== "darwin") app.quit();
});
// 在 MacOS 上,应用没有结束,但所有窗口已关闭时,重新创建一个窗口
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
修改渲染进程:index.html
<!--index.html-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="width=device-width, initial-scale=1.0">
<title>空空我啊</title>
<!-- <link rel="stylesheet" href="./src/style.css"> -->
<style>
/* 格式化样式 */
* {
margin: 0;
padding: 0;
/* box-sizing: border-box; */
/* 防止用户选中文本 */
user-select: none;
}
body {
width: 100vw;
height: 100vh;
background: #2c3e50;
/* 溢出隐藏 */
overflow: hidden;
}
/* title-bar自定义标题栏 */
.title-bar {
width: 100vw;
height: 35px;
display: flex;
align-items: center;
justify-content: space-between;
background: #ffffff9c;
-webkit-app-region: drag;
.logo {
img {
width: 30px;
height: 30px;
margin: 6px 0 0px 5px;
-webkit-app-region: no-drag;
transition: transform 0.3s ease;
&:hover {
transform: scale(1.2);
}
}
}
.form-btn {
-webkit-app-region: no-drag;
/* 最小宽度 */
min-width: 100px;
/* 按钮样式 */
button {
cursor: pointer;
font-size: 1.5rem;
cursor: pointer;
border: none;
color: #ffffffb7;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
background-color: #ffffff00;
&:hover {
color: #f6f200;
background-color: hsla(160, 100%, 37%, 0.995);
box-shadow: 0 0 15px rgba(255, 254, 254, 0.5);
}
}
.openForm {
position: absolute;
-webkit-app-region: no-drag;
top: 2px;
left: 18%;
}
/* visibility:hidden; 元素不可见,但仍然占据空间。 */
.closeForm {
visibility: hidden;
}
}
#time {
font-size: 1.5rem;
background: -webkit-linear-gradient(315deg, #e1ff00 50%, #ff0000);
/*将背景剪切成文字的形状*/
background-clip: text;
-webkit-background-clip: text;
/*文字颜色设为透明,使文字与背景融为一体*/
-webkit-text-fill-color: transparent;
/* 设置字体粗细 */
font-weight: 900;
text-shadow: 2px -1px 8px rgba(250, 80, 193, 0.323);
sub {
/* font-size: 1rem; */
text-shadow: 2px -1px 8px rgba(250, 80, 193, 0.323);
}
}
iframe {
-webkit-app-region: no-drag;
}
.window-btn {
display: flex;
min-width: 110px;
i {
cursor: pointer;
img {
width: 30px;
height: 30px;
-webkit-app-region: no-drag;
transition: transform 0.3s ease;
margin: 6px 0 0px 5px;
&:hover {
background-color: hsla(0, 0%, 40%, 0.68);
transform: scale(1.2);
}
}
}
}
}
/* 自定义标题栏 结束 */
/* content内容区 开始 */
.content {
display: flex;
flex-direction: column;
place-items: center;
gap: 20px;
color: #c8cdd7;
padding: 5rem;
h1,
a,
span {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
margin: 0 auto;
}
a {
padding: 0 0 0 0.5rem;
&:hover {
cursor: pointer;
background-color: hsla(160, 100%, 37%, 0.2);
}
}
span {
padding: 0.5rem;
}
}
h3 {
user-select: text;
color: #3ac290bb;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
}
/* 内容区 结束 */
</style>
</head>
<body>
<!--title-bar 自定义标题栏 -->
<div class="title-bar">
<a class="logo" href="https://blog.csdn.net/lulei5153" title="与妖为邻CSDN博客" class="" target="_blank">
<img src="./img/icon.png" alt="与妖为邻" />
</a>
<div class="form-btn">
<button class="openForm" onclick="openForm()">编辑</button>
<button class="closeForm" onclick="closeForm()">取消编辑</button>
</div>
<div id="time">当前时间</div>
<iframe id="tianqi" frameborder="0" width="150" height="36" scrolling="no" hspace="0"
src="https://i.tianqi.com/?c=code&id=99" style="margin-left: 20px">
</iframe>
<div class="window-btn">
<i id="minimize" onclick="minimize()">
<img src="/img/最小化.svg" alt="最小化" />
</i>
<i id="maximize" onclick="maximize()">
<img src="./img/最大化.svg" alt="最大化" />
</i>
</i>
<i id="closeMize" onclick="closeMize()">
<img src="./img/关闭.svg" alt="关闭" />
</i>
</div>
</div>
<div class="content">
<!-- 自定义标题栏 结束 -->
<h1>我们做到了!</h1>
我们成功创建了一个基于
<div><a href="https://nodejs.cn/en/learn" target="_blank" rel="noopener">Node.js</a> <span
id="node-version"></span>+
<a href="https://www.chromium.org/" target="_blank" rel="noopener">Chromium</a> <span
id="chrome-version"></span>和<a href="https://www.electronjs.org/zh/docs/latest/" target="_blank"
rel="noopener">Electron</a> <span id="electron-version"></span>
</div>的项目,并且实现了基本的功能,如:标题栏、菜单栏、编辑器、时间显示、天气显示等。
<br>
接下来,我们将继续完善这个项目,然后打包成桌面应用,欢迎大家的加入!
<pre>
<h2> 我们的项目结构如下:</h2>
<h3>
1. img:项目的图片文件。
2. node_modules:项目的依赖文件,用于安装第三方模块。
3. index.html:主页面,用于渲染 web 页面。
4. main.js:项目的入口文件,用于创建主进程。
5. package.json:用于定义项目的名称、版本、依赖等。
6. preload.js:项目的预加载文件,用于预加载渲染进程。
<!-- 7. renderer.js:项目的渲染进程文件,用于渲染页面。 -->
</h3>
</pre>
</div>
<!-- <script src="./src/renderer.js"></script> -->
</body>
<script>
/* 当前时间*/
var current_time = document.getElementById("time");
function showTime() {
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth() + 1;
var day = now.getDate();
var hour = now.getHours();
var min = now.getMinutes();
var second = now.getSeconds();
var arr_work = new Array(
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六"
);
var week = arr_work[now.getDay()];
month = month < 10 ? "0" + month : month; //时间月份个位补0
day = day < 10 ? "0" + day : day;
hour = hour < 10 ? "0" + hour : hour;
min = min < 10 ? "0" + min : min;
second = second < 10 ? "0" + second : second;
var time =
year +
"-" +
month +
"-" +
day +
"<sub id='sub'>" +
week +
"</sub>" +
hour +
":" +
min +
":" +
second;
current_time.innerHTML = time;
}
// window.setInterval("showTime(time)", 1000);
window.setInterval(showTime, 1000);
showTime();
/* 当前时间 结束 */
/* 编辑按钮的逻辑*/
const openForm = () => {
document.querySelector(".closeForm").style.visibility = "visible";
document.querySelector(".openForm").style.display = "none";
};
const closeForm = () => {
// 关闭表单的逻辑
document.querySelector(".closeForm").style.visibility = "hidden";
document.querySelector(".openForm").style.display = "block";
};
/*最大化、还原窗口*/
const maximize = () => {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
};
/* 最大化、还原窗口结束 */
/* 关闭窗口*/
// document.getElementById("closeMize").addEventListener("click", function () {
// window.close();
// });
const closeMize = () => {
window.close();
};
/* 关闭窗口结束*/
/*缩小窗口*/
let originalSize = { width: window.innerWidth, height: window.innerHeight };
const minimize = async () => {
try {
if (document.fullscreenElement) {
await document.exitFullscreen();
}
window.resizeTo(1, 1);
window.moveTo(1200, 100);
createRestoreButton();
} catch (error) {
console.error("Error exiting fullscreen: ", error);
}
};
const createRestoreButton = () => {
let button = document.createElement("button");
button.id = "restore";
button.addEventListener("click", restore);
document.body.appendChild(button);
Object.assign(button.style, {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
backgroundImage: "url('./img/icon.png')",
backgroundSize: "contain",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
width: "100px",
height: "100px",
border: "none",
cursor: "pointer",
backgroundColor: "rgba(255, 255, 255, 0)",
});
};
// 恢复窗口到原始大小
const restore = () => {
console.log("Restore button clicked");
window.resizeTo(originalSize.width, originalSize.height);
let x = screen.width / 2 - 500;
let y = screen.height / 2 - 300;
window.moveTo(x, y);
document.getElementById("restore").remove();
};
/*缩小窗口 结束*/
</script>
</html>
img文件夹图片:
关闭图标
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1718372764277" class="icon"
viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12105"
xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<path d="M511.651616 0.557806C229.358004 0.557806 0.511486 229.590226 0.511486 512.209168c0
282.572466 228.846517 511.604887 511.14013 511.604887C793.991703 1023.814055 1022.838221 794.781635
1022.838221 512.209168 1022.838221 229.590226 793.991703 0.557806 511.651616 0.557806zM333.788979
778.468652l-83.191565-82.773284 181.952501-183.253821L249.481997 330.303143l82.726807-83.238041 183.067919
182.091929 181.906025-183.207346 83.238041 82.773283-181.952501 183.253822 183.021443 182.091928-82.726808
83.284516-183.021443-182.138404-181.952501 183.253822z"
fill="#FF0000"
p-id="12106"></path></svg>
最大化图标
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1718375106010" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3046" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M128.576377 895.420553 128.576377 128.578424l766.846222 0 0 766.842129L128.576377 895.420553zM799.567461 224.434585 224.432539 224.434585l0 575.134923 575.134923 0L799.567461 224.434585z" fill="#020202" p-id="3047"></path></svg>
最小化图标
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1718373169139" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16678" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M213.333333 469.333333m21.333334 0l554.666666 0q21.333333 0 21.333334 21.333334l0 42.666666q0 21.333333-21.333334 21.333334l-554.666666 0q-21.333333 0-21.333334-21.333334l0-42.666666q0-21.333333 21.333334-21.333334Z" fill="#4A4A4A" p-id="16679"></path></svg>