一、背景
接了个小需求,已有网站,做了个electron的壳,需要添加右键菜单
1.复制图片为base64
2.另存为图片
3.复制图片地址
二、首先需要添加右键菜单
1.主线程 background.js添加右键菜单内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
const rightMenu = initRightMenu(); function initRightMenu() { const rightTemplate = [ { label: "复制图片为base64", click: () => { console.log("复制图片为base64"); }, }, { label: "另存为图片", click: () => { console.log("另存为图片"); }, }, { label: "复制图片URL", click: () => { console.log("复制图片URL"); }, }, ]; const menu = Menu.buildFromTemplate(rightTemplate); return menu; }
|
2.页面右键要能调用
需要页面右键能够响应
那么我们需要在页面上能够获取到右键的点击事件
1 2 3 4 5
| window.addEventListener("contextmenu", (e) => { e.preventDefault(); });
|
3.通知主线程响应
通过preload
为window对象挂上一个rightMenu
属性用于沟通调用
1 2 3 4 5 6 7 8
| contextBridge.exposeInMainWorld("rightMenu", { show: (domId) => ipcRenderer.invoke("show-context-menu", { domId, }), });
|
1 2 3 4 5 6 7 8 9 10 11 12
| window.addEventListener("contextmenu", (e) => { e.preventDefault(); const domName = e.target.localName; if (domName === "img") { if (e.target.id === "") { const date = new Date().valueOf(); e.target.id = date; } window.rightMenu.show(e.target.id); } });
|
因为我们的目标是图片,所以判断一下,是图片才调用右键展示
同时我们需要知道我们需要操作哪个dom,所以为其设置一个id,方便后续操作
1 2 3 4 5 6 7 8
| ipcMain.handle("show-context-menu", (event, args) => { const { domId } = args; clickDomId = domId; rightMenu.popup({ window: BrowserWindow.getFocusedWindow().webContents, }); });
|
展示
4.实现内容
好像有点简单,随便百度了几个方法,就不多说了,直接放代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| ipcRenderer.on("base64", (event, args) => { const { domId } = args; const element = document.getElementById(domId); imageToBase64(element.currentSrc); });
ipcRenderer.on("saveImage", (event, args) => { const { domId } = args; const element = document.getElementById(domId); const nameArray = element.currentSrc.split("/"); const tmpArray = nameArray[nameArray.length - 1].split("."); const name = tmpArray[0]; download(element.currentSrc, name); });
ipcRenderer.on("copyUrl", (event, args) => { const { domId } = args; const element = document.getElementById(domId); copy(element.currentSrc); });
const getBase64Image = (img) => { const canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); let ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase(); if (ext === "jpg") { ext = "jpeg"; } const dataURL = canvas.toDataURL("image/" + ext); return dataURL; };
const imageToBase64 = (url) => { let image = new Image(); image.crossOrigin = ""; image.src = url; image.onload = function () { const base64 = getBase64Image(image); copy(base64); }; };
const download = (data, name) => { if (!data) { return; } getUrlBase64(data).then((base64) => { let a = document.createElement("a"); a.style.display = "none"; a.download = name; a.href = base64; document.body.appendChild(a); a.click(); }); }; const getUrlBase64 = (url) => { return new Promise((resolve) => { let canvas = document.createElement("canvas"); let ctx = canvas.getContext("2d"); let img = new Image(); img.crossOrigin = "Anonymous"; img.src = url; img.onload = function () { canvas.height = 300; canvas.width = 300; ctx.drawImage(img, 0, 0, 300, 300); let dataURL = canvas.toDataURL("image/png"); canvas = null; resolve(dataURL); }; }); };
|
那么如果是加载别人远程页面,没有页面代码,比如我们是个浏览器,如何实现这个功能?
其实也有方法,我们可以通过注入的方式去做
可见无星的electron之旅(九)—— JS注入
在页面加载完成以后,通过preload
注入代码即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| document.addEventListener("DOMContentLoaded", () => { window.addEventListener("contextmenu", (e) => { e.preventDefault(); const domName = e.target.localName; if (domName === "img") { if (e.target.id === "") { const date = new Date().valueOf(); e.target.id = date; } ipcRenderer.invoke("show-context-menu", { domId: e.target.id, }); } }); });
|
通过这段代码,我们可以为不同样式标签添加不同操作,并且不需要修改网页代码,自然像浏览器一样,添加右键菜单
效果