electron抽奖系统中的进程通讯

100 阅读6分钟

一.制作一个抽奖页面

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>2023Web前端开发竞赛抽奖</title>
    <link rel="stylesheet" href="css/an.css" />
    <link rel="stylesheet" href="css/index.css" />
  </head>
  <body>
    <div style="display: none">
      <audio id="mp3_bg" src="音乐/bg.mp3" controls loop></audio>
      <audio id="mp3_20" src="音乐/20.mp3" controls></audio>
      <audio id="mp3_40" src="音乐/40.mp3" controls></audio>
      <audio id="mp3_60" src="音乐/60.mp3" controls></audio>
      <audio id="mp3_80" src="音乐/80.mp3" controls></audio>
      <audio id="mp3_100" src="音乐/100.mp3" controls></audio>
    </div>

    <h2 id="C" class="b">腾飞人才</h2>
    <main id="A" class="b">
      <div class="giftBox">
        <i>15</i>
      </div>
      <div class="giftBox"></div>
      <div class="giftBox"></div>
      <div class="giftBox"></div>
      <div class="giftBox"></div>
      <div class="giftBox"></div>
    </main>

    <div id="show" class="b">
      <h2 id="moneyText">恭喜你获得</h2>
      <img id="myImg" class="myImg" src="img/bai.jpg" />
      <span id="myText">继续</span>
    </div>

    <button id="btn">活动开始</button>
    <!-- 遮罩层 -->
    <div id="blackDiv"></div>

    <script src="js/fun.js"></script>
    <script src="js/index.js"></script>
  </body>
</html>

fun.js

function fullScreen(){

	console.log(window.innerWidth+window.scrollWidth+'px')
	console.log(window.innerHeight+window.scrollHeight+'px')

	blackDiv.style.width = window.innerWidth+window.scrollHeight+'px';
	blackDiv.style.height = window.innerHeight+window.scrollHeight+'px';
	
}//fullScreen

//数组洗牌随机算法 传入数组,打乱数据
function shuffle(arr) { 
	let m = arr.length;
	let t, i;
	while (m) {
		i = Math.floor(Math.random() * m--)
		t = arr[m];
		arr[m] = arr[i];
		arr[i] = t;
	}
	return arr;
}//shuffle


function shuffleArray(array) {
	for (let i = array.length - 1; i > 0; i--) {
	  const j = Math.floor(Math.random() * (i + 1));
	  [array[i], array[j]] = [array[j], array[i]];
	}
	return array;
  }

index.js

window.playing.抽奖数据(async (value) => {
  let n = 100;
  let arr = [];
  console.log(value);
  for (let i of value) {
    console.log(i);
    for (let j = 0; j < i.nub; j++) {
      arr.push({
        money: i.等级,
        name: i.name,
      });
    }
  }
  console.log(arr);
  // for (let i = 0; i < 49; i++) {
  //   arr.push(20);
  // }

  let myText = document.querySelector("#myText");
  let myImg = document.querySelector("#myImg");

  btn.click();

  // mp3_bg.play()	//because the user didn't interact with the document first

  //显示所有抽奖盒子在页面
  let 文本 = "";
  arr = shuffle(arr); //打乱数组

  for (let i = 0; i < arr.length; i++) {
    let money = arr[i].money;
    let text = arr[i].name;
    //   if (money == 60 || money == 80) {
    //如果是 60或者 80 显示金额
    // text = `<span style="color:black">${money}</span>`;
    //   }
    let div = `
	<div class="giftBox gift" data-money="${money}"  data-name="${text}">
		<i>${text}</i>
	</div>`;

    文本 += div;
  }
  A.innerHTML = 文本;

  //交互 让所有的div可以被点击
  let divArr = document.querySelectorAll("#A div");
  for (let div of divArr) {
    div.onclick = function () {
      this.onclick = null;
      let 样式 = this.classList;
      样式.remove("giftBox");

      let money = this.dataset.money;
      let name = this.dataset.name;
      let src = "";
      console.log(typeof money);
      let num = parseInt(Math.random() * 4 + 1);
      switch (money) {
        case "100":
          mp3_100.play();
          break;
        case "80":
          mp3_80.play();
          break;
        case "60":
          mp3_60.play();
          break;
        case "40":
          mp3_40.play();
          break;
        default:
          mp3_20.play();
          break;
      }

      样式.add("open_pick");

      //显示出来

      myImg.src = "img/" + money + "/" + num + ".webp";

      moneyText.innerHTML = `${name}`;
      this.innerHTML = `<i>${name}</i>`;

      blackDiv.style.display = "block";
      show.style.visibility = "visible";
    }; //div
  } //for
});

let mySpan = document.querySelector("#show span");

mySpan.onclick = function () {
  if (blackDiv.style.display == "block") {
    show.style.visibility = "hidden";
    blackDiv.style.display = "none";
  }
};

//获取所有的红包
let giftBoxArr = document.querySelectorAll(".giftBox");
//定时器(自定义函数,时间)
setInterval(function () {
  let n = parseInt(Math.random() * giftBoxArr.length);

  if (document.querySelector(".move")) {
    //找到谁在运动
    document.querySelector(".move").classList.remove("move");
  }

  giftBoxArr[n].classList.add("move");
}, 1500);

window.addEventListener("resize", function () {
  // Handle resize event here
  fullScreen();
});

btn.onclick = function () {
  this.style.display = "none";
  mp3_bg.play();
  blackDiv.style.display = "none";
}; //btn

fullScreen();

代码图

image.png

效果图

image.png

二. 创建electron项目,将抽奖页创建窗口

项目入门文件 main.js

const { app, BrowserWindow } = require('electron')
const path = require('path')  // 引入 path 模块

let 主文件路径 = path.join(__dirname, './myHTML/钱呈/index.html')

const 创建窗口 = () => {

    let 窗口参数 = {
        width: 800,
        height: 600,
        frame: false, // 设置为false以创建一个无边框窗口
        fullscreen: true, // 设置全屏属性为true  
    }
    const 窗口 = new BrowserWindow(窗口参数)
    //引入文件必须使用完整路径

    窗口.loadFile(主文件路径)
}


app.whenReady().then(() => {
    创建窗口()
    //如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
    app.on('activate', () => {
        let 窗口数量 = BrowserWindow.getAllWindows().length
        if (窗口数量 === 0) { 创建窗口() }
    })
})


app.on('window-all-closed', () => {
    app.quit()  //
})

启动项目效果图

image.png

三.数据修改页

数据.html

在本页面中,我使用了vue.js,请自行引入

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>设置数值</title>
    <script src="js/vue3.js"></script>
    <style>
      table {
        width: 300px;
        height: 200px;
      }
      td {
        text-align: center;
      }
      input {
        display: block;
        width: 100%;
        height: 100%;
        border: none;
        text-align: center;
      }
      button {
        display: block;
        width: 300px;
        height: 100%;
        border: none;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <main id="app">
      <table border="1" cellspacing="0" cellpadding="2">
        <tr>
          <th>等级</th>
          <th>名称</th>
          <th>数量</th>
        </tr>
        <tr v-for="(item,index) in data" :key="index">
          <td>{{index+1}}</td>
          <td><input type="text" v-model="item.name" maxlength="5" /></td>
          <td><input type="number" v-model="item.nub" maxlength="2" /></td>
        </tr>
      </table>
      <div>
        <button @click="open">打开抽奖页</button>
      </div>
    </main>
    <script src="js/index_vue3.js"></script>
  </body>
</html>

index_vue3.js

let data = {
  data: [
    {
      等级: 100,
      name: "",
      nub: 0,
    },
    {
      等级: 80,
      name: "",
      nub: 0,
    },
    {
      等级: 60,
      name: "",
      nub: 0,
    },
    {
      等级: 40,
      name: "",
      nub: 0,
    },
    {
      等级: 20,
      name: "",
      nub: 0,
    },
  ],
};

const App = {
  data() {
    return data;
  },
};

//Vue.创建应用(配置).挂载(元素ID)
Vue.createApp(App).mount("#app");

效果图

image.png

四、数据页加入到窗口中

创建预加载脚本——preload.js

const { contextBridge, ipcRenderer } = require("electron");

// 在主进程中,将"通讯API"暴露给渲染进程
contextBridge.exposeInMainWorld("playing", {
});

修改main.js

const { app, BrowserWindow, ipcMain, Menu } = require("electron");
const path = require("path"); // 引入 path 模块

let 主文件路径 = path.join(__dirname, "./myHTML/钱呈/index.html");

const 创建窗口 = (传递的值) => {
  let 窗口参数 = {
    width: 800,
    height: 600,
    frame: true,
    fullscreen: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: true,
      javascript: true,
      preload: path.join(__dirname, "preload.js"),
    },
  };
  const 窗口 = new BrowserWindow(窗口参数);
  窗口.loadFile(主文件路径);
};



const 数据窗口 = () => {
  let 窗口参数 = {
    width: 325,
    height: 270,
    resizable: false, // 设置是否可缩放
    frame: true, // 设置为false以创建一个无边框窗口
    fullscreen: false, // 设置全屏属性为true
    webPreferences: {
      nodeIntegration: true, // 启用 Node.js 集成,允许在渲染进程中使用 Node.js 模块
      contextIsolation: true, // 启用上下文隔离,增加安全性,防止渲染进程直接访问主进程的 API
      javascript: true, // 允许页面执行 JavaScript 代码
      preload: path.join(__dirname, "preload.js"), // 在渲染进程执行之前,预加载指定的脚本
    },
  };
  
  const 窗口 = new BrowserWindow(窗口参数);
  窗口.setMenuBarVisibility(false);
  //引入文件必须使用完整路径
  窗口.loadFile("./myHTML/钱呈/数据.html");
  
};

app.whenReady().then(() => {
  数据窗口();
  //   创建窗口();
  //如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
  app.on("activate", () => {
    let 窗口数量 = BrowserWindow.getAllWindows().length;
    if (窗口数量 === 0) {
      创建窗口();
    }
  });
});

app.on("window-all-closed", () => {
  app.quit(); //
});

五.进行通讯,修改数据

index_vue3.js

const App = {
  data() {
    return data;
  },
  methods: {
    //自定义方法(函数)
    open() {
      let flag = true;
      let 数量 = 0;
      let names = [];
      for (let i = 0; i < this.data.length; i++) {
        if (this.data[i].name == "") {
          alert("请填写完整信息!");
          return;
        }
        //查询是否有相同信息
        if (names.includes(this.data[i].name)) {
          // Check if name already exists in the array
          alert("数组中有相同信息!");
          return;
        }
        names.push(this.data[i].name); // Add name to the array
        if (this.data[i].nub < 0) {
          alert("数量不能为负数!");
          return;
        }
        if (this.data[i].nub % 1 != 0) {
          alert("数量不能为小数!");
          return;
        }
        数量 += this.data[i].nub;

        if (数量 > 100) {
          alert("数量超过100!");
          return;
        }
      }
      if (数量 == 0) {
        alert("数量不能等于0!");
        return;
      }
      let API = window.playing.打开页面;
      //转为字符串
      let data = JSON.stringify(this.data);
      API(data);
    },
  },
};

main.js

const { app, BrowserWindow, ipcMain, Menu } = require("electron");
const path = require("path"); // 引入 path 模块

let 主文件路径 = path.join(__dirname, "./myHTML/钱呈/index.html");

const 创建窗口 = (传递的值) => {
  let 窗口参数 = {...}
  const 窗口 = new BrowserWindow(窗口参数);
  const menu = Menu.buildFromTemplate([
    {
      label: "更改数据",
      click: async () => {
        数据窗口();
        //关闭当前页面
        窗口.close();
      },
    },
  ]);

  Menu.setApplicationMenu(menu);
  窗口.loadFile(主文件路径);

  // 在创建窗口后,使用webContents发送值到渲染进程
  窗口.webContents.on("did-finish-load", () => {
    窗口.webContents.send("传递的值", 传递的值);
  });
};

function 数据处理(窗口, 数据) {
  console.log(数据);
  const 当前窗口参数 = 窗口.sender;
  const 当前窗口 = BrowserWindow.fromWebContents(当前窗口参数);
  数据 = JSON.parse(数据);
  创建窗口(数据);
  //关闭当前窗口
  当前窗口.close();
}

const 数据窗口 = () => {
  let 窗口参数 = {....};
  const 窗口 = new BrowserWindow(窗口参数);
  窗口.setMenuBarVisibility(false);
  //引入文件必须使用完整路径
  ipcMain.on("抽奖数据", 数据处理);
  窗口.loadFile("./myHTML/钱呈/数据.html");
};

preload.js

const { contextBridge, ipcRenderer } = require("electron");

// 在主进程中,将"通讯API"暴露给渲染进程
contextBridge.exposeInMainWorld("playing", {
  // 模式一:将title发送给渲染进程
  打开页面: (data) => ipcRenderer.send("抽奖数据", data),

  // 模式三:通过回调函数接收主进程发送的值
  抽奖数据: (callback) =>
    ipcRenderer.on("传递的值", (_event, value) => callback(value)),
});

index.js

window.playing.抽奖数据(async (value) => {
  let n = 100;
  let arr = [];
  console.log(value);
  for (let i of value) {
    console.log(i);
    for (let j = 0; j < i.nub; j++) {
      arr.push({
        money: i.等级,
        name: i.name,
      });
    }
  }
  console.log(arr);
  // for (let i = 0; i < 49; i++) {
  //   arr.push(20);
  // }

  let myText = document.querySelector("#myText");
  let myImg = document.querySelector("#myImg");

  btn.click();

  // mp3_bg.play()	//because the user didn't interact with the document first

  //显示所有抽奖盒子在页面
  let 文本 = "";
  arr = shuffle(arr); //打乱数组

  for (let i = 0; i < arr.length; i++) {
    let money = arr[i].money;
    let text = arr[i].name;
    //   if (money == 60 || money == 80) {
    //如果是 60或者 80 显示金额
    // text = `<span style="color:black">${money}</span>`;
    //   }
    let div = `
	<div class="giftBox gift" data-money="${money}"  data-name="${text}">
		<i>${text}</i>
	</div>`;

    文本 += div;
  }
  A.innerHTML = 文本;

  //交互 让所有的div可以被点击
  let divArr = document.querySelectorAll("#A div");
  for (let div of divArr) {
    div.onclick = function () {
      this.onclick = null;
      let 样式 = this.classList;
      样式.remove("giftBox");

      let money = this.dataset.money;
      let name = this.dataset.name;
      let src = "";
      console.log(typeof money);
      let num = parseInt(Math.random() * 4 + 1);
      switch (money) {
        case "100":
          mp3_100.play();
          break;
        case "80":
          mp3_80.play();
          break;
        case "60":
          mp3_60.play();
          break;
        case "40":
          mp3_40.play();
          break;
        default:
          mp3_20.play();
          break;
      }

      样式.add("open_pick");

      //显示出来

      myImg.src = "img/" + money + "/" + num + ".webp";

      moneyText.innerHTML = `${name}`;
      this.innerHTML = `<i>${name}</i>`;

      blackDiv.style.display = "block";
      show.style.visibility = "visible";
    }; //div
  } //for
});

let mySpan = document.querySelector("#show span");

mySpan.onclick = function () {
  if (blackDiv.style.display == "block") {
    show.style.visibility = "hidden";
    blackDiv.style.display = "none";
  }
};

//获取所有的红包
let giftBoxArr = document.querySelectorAll(".giftBox");
//定时器(自定义函数,时间)
setInterval(function () {
  let n = parseInt(Math.random() * giftBoxArr.length);

  if (document.querySelector(".move")) {
    //找到谁在运动
    document.querySelector(".move").classList.remove("move");
  }

  giftBoxArr[n].classList.add("move");
}, 1500);

window.addEventListener("resize", function () {
  // Handle resize event here
  fullScreen();
});

btn.onclick = function () {
  this.style.display = "none";
  mp3_bg.play();
  blackDiv.style.display = "none";
}; //btn

fullScreen();

最终效果

image.png

image.png