网站建设注意哪些事项,非常好的网站建设公司,深圳网络营销推广公司哪家好,用ai做网页设计实现效果 实现思路 
创建两个window#xff0c;一个叫mainWindow#xff0c;一个叫cutWindowmainWindow#xff1a;主界面用来展示截图结果cutWindow#xff1a;截图窗口#xff0c;加载截图页面和截图交互逻辑mainWindow 页面点击截图#xff0c;让cutWIndow 来实现具体…实现效果 实现思路 
创建两个window一个叫mainWindow一个叫cutWindowmainWindow主界面用来展示截图结果cutWindow截图窗口加载截图页面和截图交互逻辑mainWindow 页面点击截图让cutWIndow 来实现具体截图逻辑cutWindow截图完后把截图send给mainWindow页面 
截图过程-时序图 创建项目 
我在网上找了一大圈没有找到一个合适的模板要么环境太老、要么配置各种缺失不完善、要么打包出来各种问题等等说实话坑还真不少无意间找到一个特别好的脚手架它简单又完善。推荐给大家electron-vite 所以接下来直接用创建命令 
yarn create quick-start/electron安装依赖 
vue-router切换加载首页和截图页面konva完成截图交互的库 
yarn add konva vue-router核心代码 
为了更好的展示添加的内容提供如下目录结构图方便理解 
目录结构 主进程 src/main/index.js import {app,shell,BrowserWindow,ipcMain,screen,desktopCapturer,globalShortcut
} from electron
import { join } from path
import { electronApp, optimizer, is } from electron-toolkit/utils
import icon from ../../resources/icon.png?assetlet mainWindow
let cutWindowfunction closeCutWindow() {cutWindow  cutWindow.close()cutWindow  null
}function createMainWindow() {mainWindow  new BrowserWindow({width: 900,height: 670,show: false,autoHideMenuBar: true,...(process.platform  linux ? { icon } : {}),webPreferences: {preload: join(__dirname, ../preload/index.js),sandbox: false}})mainWindow.on(ready-to-show, ()  {mainWindow.show()})mainWindow.webContents.setWindowOpenHandler((details)  {shell.openExternal(details.url)return { action: deny }})console.log(loadURL:, process.env[ELECTRON_RENDERER_URL])if (is.dev  process.env[ELECTRON_RENDERER_URL]) {mainWindow.loadURL(process.env[ELECTRON_RENDERER_URL])} else {mainWindow.loadFile(join(__dirname, ../renderer/index.html))}mainWindow.on(closed, ()  {closeCutWindow()})
}function registerShortcut() {//! 截图快捷键globalShortcut.register(CommandOrControlAltC, ()  {openCutScreen()})globalShortcut.register(Esc, ()  {closeCutWindow()mainWindow.show()})globalShortcut.register(Enter, sendFinishCut)
}app.whenReady().then(()  {// Set app user model id for windowselectronApp.setAppUserModelId(com.electron)// Default open or close DevTools by F12 in development// and ignore CommandOrControl  R in production.// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils//! 开发模式win 环境F12 和 mac os 环境CommandOrControl  R 打开 DevToolsapp.on(browser-window-created, (_, window)  {optimizer.watchWindowShortcuts(window)})createMainWindow()registerShortcut()openMainListener()app.on(activate, function () {if (BrowserWindow.getAllWindows().length  0) createMainWindow()})
})app.on(window-all-closed, ()  {if (process.platform ! darwin) {globalShortcut.unregisterAll()app.quit()}
})function getSize() {const { size, scaleFactor }  screen.getPrimaryDisplay()return {width: size.width * scaleFactor,height: size.height * scaleFactor}
}function createCutWindow() {const { width, height }  getSize()cutWindow  new BrowserWindow({width,height,autoHideMenuBar: true,useContentSize: true,movable: false,frame: false,resizable: false,hasShadow: false,transparent: true,fullscreenable: true,fullscreen: true,simpleFullscreen: true,alwaysOnTop: false,webPreferences: {preload: join(__dirname, ../preload/index.js),nodeIntegration: true,contextIsolation: false}})console.log(createCutWindow:, is.dev, process.env[ELECTRON_RENDERER_URL])if (is.dev  process.env[ELECTRON_RENDERER_URL]) {let url  process.env[ELECTRON_RENDERER_URL]  /#/cutconsole.log(createCutWindow: loadURL, url)cutWindow.loadURL(url)} else {cutWindow.loadFile(path.join(__dirname, ../renderer/index.html))}cutWindow.maximize()cutWindow.setFullScreen(true)
}function sendFinishCut() {cutWindow  cutWindow.webContents.send(FINISH_CUT)
}function openCutScreen() {closeCutWindow()mainWindow.hide()createCutWindow()cutWindow.show()
}function openMainListener() {ipcMain.on(OPEN_CUT_SCREEN, openCutScreen)ipcMain.on(SHOW_CUT_SCREEN, async (e)  {let sources  await desktopCapturer.getSources({types: [screen],thumbnailSize: getSize()})cutWindow  cutWindow.webContents.send(GET_SCREEN_IMAGE, sources[0])})ipcMain.on(FINISH_CUT_SCREEN, async (e, cutInfo)  {closeCutWindow()mainWindow.webContents.send(GET_CUT_INFO, cutInfo)mainWindow.show()})ipcMain.on(CLOSE_CUT_SCREEN, async (e)  {closeCutWindow()mainWindow.show()})
}渲染器 scr/main.js import { createApp } from vue
import App from ./App.vue
import router from ./routerconst app  createApp(App)
app.use(router)
app.mount(#app)src/router/index.js import { createRouter, createWebHashHistory } from vue-routerconst routes  [{ path: /, redirect: /home },{path: /home,name: home,component: ()  import(../pages/Home/index.vue)},{path: /cut,name: cut,component: ()  import(../pages/Cut/index.vue)}
]const router  createRouter({history: createWebHashHistory(),routes
})export default routersrc/App.vue templaterouter-view/router-view
/templatescript setup
/scriptstyle langless
import ./assets/css/styles.less;
/stylesrc/pages/index.vue首页 templatediv classcontainerbutton clickhandleCutScreen截屏/buttondivimg :srcpreviewImagestylemax-width: 100% //div/div
/templatescript setup
import { ref } from vue;
const { ipcRenderer }  window.electron;
const previewImage  ref();async function handleCutScreen() {await ipcRenderer.send(OPEN_CUT_SCREEN);ipcRenderer.removeListener(GET_CUT_INFO, getCutInfo);ipcRenderer.on(GET_CUT_INFO, getCutInfo);
}function getCutInfo(event, pic) {previewImage.value  pic;
}
/scriptsrc/pages/cut.vue截图界面 templatediv classcontainer:stylebackground-image:url(  bg  )refcontainermousedownonMouseDownmousemoveonMouseMovemouseuponMouseUp/div
/template
script setup
import Konva from konva;
import { ref, onMounted } from vue;const { ipcRenderer }  window.electron;
let container  ref(null);
let bg  ref();
let stage, layer, rect, transformer;onMounted(()  {ipcRenderer.send(SHOW_CUT_SCREEN);ipcRenderer.removeListener(GET_SCREEN_IMAGE, getSource);ipcRenderer.on(GET_SCREEN_IMAGE, getSource);ipcRenderer.on(FINISH_CUT, confirmCut);
});async function getSource(event, source) {const { thumbnail }  source;const pngData  await thumbnail.toDataURL(image/png);bg.value  pngData;render();
}function render() {stage  createStage();layer  createLayer(stage);
}function createStage() {return new Konva.Stage({container: container.value,width: window.innerWidth,height: window.innerHeight,});
}function createLayer(stage) {let layer  new Konva.Layer();stage.add(layer);layer.draw();return layer;
}function createRect(layer, x, y, width, height, alpha, draggable) {let rect  new Konva.Rect({x,y,width,height,fill: rgba(0,0,255,${alpha}),draggable});layer.add(rect);return rect;
}let isDown  false;
let rectOption  {};
function onMouseDown(e) {if (rect || isDown) {return;}isDown  true;const { pageX, pageY }  e;rectOption.x  pageX || 0;rectOption.y  pageY || 0;rect  createRect(layer, pageX, pageY, 0, 0, 0.25, false);rect.draw();
}function onMouseMove(e) {if (!isDown) return;const { pageX, pageY }  e;let w  pageX - rectOption.x;let h  pageY - rectOption.y;rect.remove();rect  createRect(layer, rectOption.x, rectOption.y, w, h, 0.25, false);rect.draw();
}function onMouseUp(e) {if (!isDown) {return;}isDown  false;const { pageX, pageY }  e;let w  pageX - rectOption.x;let h  pageY - rectOption.y;rect.remove();rect  createRect(layer, rectOption.x, rectOption.y, w, h, 0, true);rect.draw();transformer  createTransformer(rect);layer.add(transformer);
}function createTransformer(rect) {let transformer  new Konva.Transformer({nodes: [rect],rotateAnchorOffset: 60,enabledAnchors: [top-left, top-right, bottom-left, bottom-right]});return transformer
}/*** 根据选择区域生成图片* param {*} info */
async function getCutImage(info) {const { x, y, width, height }  info;let img  new Image();img.src  bg.value;let canvas  document.createElement(canvas);let ctx  canvas.getContext(2d);canvas.width  ctx.width  width;canvas.height  ctx.height  height;ctx.drawImage(img, -x, -y, window.innerWidth, window.innerHeight);return canvas.toDataURL(image/png);
}/*** 确认截图*/
async function confirmCut() {const { width, height, x, y, scaleX  1, scaleY  1 }  rect.attrs;let _x  width  0 ? x : x  width * scaleX;let _y  height  0 ? y : y  height * scaleY;let pic  await getCutImage({x: _x,y: _y,width: Math.abs(width) * scaleX,height: Math.abs(height) * scaleY,});ipcRenderer.send(FINISH_CUT_SCREEN, pic);
}/*** 关闭截图*/
function closeCut() {ipcRenderer.send(CLOSE_CUT_SCREEN);
}
/scriptstyle langscss scoped
.container {position: fixed;top: 0;bottom: 0;left: 0;right: 0;width: 100%;height: 100%;overflow: hidden;background-color: transparent;background-size: 100% 100%;background-repeat: no-repeat;border: 2px solid blue;box-sizing: border-box;
}
/style总结 
虽然实现了核心功能但是仅支持主屏幕截图不支持多屏幕截图同时还遗留诸多问题后面单独一篇更新解决 
完整demo 传送门顺便帮忙点个star感谢~ 
参考文献 
https://juejin.cn/post/7111115472182968327https://www.electronjs.org/docs/latest/tutorial/keyboard-shortcutshttps://konvajs.org/docs/select_and_transform/Basic_demo.htmlhttps://stackoverflow.com/questions/40360109/content-security-policy-img-src-self-data/62213224#62213224 
更多 
家人们我最近花了2个多月开源了一个文章发布助手artipub可以帮你一键将markdown发布至多平台发布和更新方便大家更好的传播知识和分享你的经验。 目前已支持平台个人博客、Medium、Dev.to未来会支持更多平台 官网地址https://artipub.github.io/artipub/ 仓库地址https://github.com/artipub/artipub 
目前库已可以正常使用欢迎大家体验、如果你有任何问题和建议都可以在Issue给我进行反馈。 如果你感兴趣特别欢迎你的加入让我们一起完善好这个工具。 帮忙点个star⭐让更多人知道这个工具感谢大家