The background,

With a small demand, the existing website, made a electron shell, need to add right-click menu 1. Copy the image as base64. 2. Save the image as base64. 3

Two, the first need to add right-click menu

1. Add right-click menu contents to background-js

// background.js
///////////
const rightMenu = initRightMenu();
function initRightMenu() {
  const rightTemplate = [
    {
      label: "Copy the image to base64".click: () = > {
        console.log("Copy the image to base64"); }, {},label: "Save as picture".click: () = > {
        console.log("Save as picture"); }, {},label: "Copy image URL".click: () = > {
        console.log("Copy image URL"); }},];const menu = Menu.buildFromTemplate(rightTemplate);
  return menu;
}
///////////
Copy the code

2. Right-click the page to be able to call

Page right-click is required to respond

So we need to be able to get right click events on the page

// Page entry, such as vue main.js
window.addEventListener("contextmenu".(e) = > {
  e.preventDefault();
  // TODO informs the main thread
});
Copy the code

3. Notify the main thread of the response

Preload attaches a rightMenu property to the window object for communication calls

// preload.js
contextBridge.exposeInMainWorld("rightMenu", {
  show: (domId) = >
    ipcRenderer.invoke("show-context-menu", {
      domId,
    }),
});

Copy the code
// main.js
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); }});Copy the code

Because our target is the image, so to determine the image is called right click display

We also need to know which DOM we need to manipulate, so give it an ID for subsequent operations

// background.js
ipcMain.handle("show-context-menu".(event, args) = > {
  const { domId } = args;
  clickDomId = domId;
  rightMenu.popup({
    window: BrowserWindow.getFocusedWindow().webContents,
  });
});
Copy the code

show

4. Implement content

Seems to be a little simple, literally Baidu a few methods, not much to say, directly put the code

// preload.js
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];
  // console.log(nameArray);
  download(element.currentSrc, name);
});

ipcRenderer.on("copyUrl".(event, args) = > {
  const { domId } = args;
  const element = document.getElementById(domId);
  copy(element.currentSrc);
});

// base64
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"; // This is because if it is JPG, it will recognize image/ PNG
  }
  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);
    // console.log(base64);
    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"; // Allow cross-domain
    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);
    };
  });
};

Copy the code

So if we’re loading someone else’s remote page and there’s no page code, like we’re a browser, how do we do that?

There’s a way to do it, we can do it by injection

Visible starless electron journey (9) — JS injection

After the page is loaded, you can inject the code through Preload

// preload.js
document.addEventListener("DOMContentLoaded".() = > {
  // Some actions that need to be introduced after the page content is loaded
  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);
      ipcRenderer.invoke("show-context-menu", {
        domId: e.target.id, }); }}); });Copy the code

With this code, we can add different actions for different styles of tags without changing the code of the web page, just like a browser, adding right-click menus

The effect