# 前言

想要实现截图功能,需要设置一个全屏隐藏菜单栏且透明的窗口,在窗口上放上屏幕的截图,然后监听鼠标,获取两次鼠标点击的位置,根据这个位置将图片用 canvas.drawImage 方法将图片写入 canvas 标签。然后再做保存或者写入剪切板的操作。

# 一、基本功能

# 一、进程间通信

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
//渲染进程
<el-button type="primary" @click="screenHot">截图</el-button> //设置一个按钮。
screenHot(){
ipcRenderer.send('screenHot')
}//向主进程发送消息。

//主进程
let fullScreen
ipcMain.on('screenHot',async()=>{
win.hide()//主窗口隐藏
//创建一个全屏且隐藏菜单栏的窗口。
fullScreen= new BrowserWindow({
autoHideMenuBar: true, // 自动隐藏菜单栏
useContentSize: true, // width 和 height 将设置为 web 页面的尺寸
movable: false, // 是否可移动
frame: false, // 无边框窗口
resizable: false, // 窗口大小是否可调整
hasShadow: false, // 窗口是否有阴影
transparent: true, // 使窗口透明
fullscreenable: true, // 窗口是否可以进入全屏状态
fullscreen: true, // 窗口是否全屏
simpleFullscreen: true, // 在 macOS 上使用 pre-Lion 全屏
alwaysOnTop: false, // 窗口是否永远在别的窗口的上面
webPreferences: {
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
await fullScreen.loadURL(process.env.WEBPACK_DEV_SERVER_URL+'screenHot.html')
} else {
createProtocol('app')
fullScreen.loadURL('app://./screenHot.html')//加载页面
}
})

ipcMain.on('getFullScreen',async() => {
//获取屏幕大小,以及缩放因子scaleFactor。
const { size, scaleFactor } = screen.getPrimaryDisplay()
const sources = await desktopCapturer.getSources({
types:['screen'],
thumbnailSize: {
width:size.width*scaleFactor,
height:size.height*scaleFactor
}
})
// 向渲染进程发送屏幕截图
fullScreen.webContents.send('sendFullScreen', sources[0],size)
})

# 二、渲染进程获取桌面截图

1
2
3
4
5
6
7
8
9
10
11
<div>
<img>
<canvas></canvas>
</div>
mounted(){
let img = document.querySelector('img')
ipcRenderer.send('getFullScreen')
ipcRenderer.on('sendFullScreen', (event, message) => {
img.src = message.thumbnail.toDataURL()
})
}

# 三、监听鼠标获取坐标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
methods:{
//获取第一次鼠标按下时的坐标
getStartPostion(e){
this.startX = e.clientX
this.startY = e.clientY
},
//获取移动时的坐标
getlastPostion(e){
this.endX = e.clientX
this.endY = e.clientY
},
//删除mousemove的监听事件
getfinallyPostion(){
document.removeEventListener('mousemove',this.getlastPostion)
}
}
mounted(){
document.addEventListener('mousedown',this.getStartPostion)
document.addEventListener('mousemove',this.getlastPostion)
document.addEventListener('mouseup',this.getfinallyPostion)
}

# 四、根据坐标生成一个矩形的截图区域

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
<div v-show="isShowCutScreen" :style="{
position: 'absolute',
left: startX + 'px',
top: startY + 'px',
width: (endX - startX) + 'px',
height: (endY - startY) + 'px',
border: '2px solid black',
}">
</div>

data(){
return{
isShowCutScreen:false,
startX:0,
startY:0,
endX:0,
endY:0,
}
}

//鼠标第一个点击时,截图区域展示出来
getStartPostion(e){
if(!this.isShowCutScreen){
this.isShowCutScreen = true
}else{
return
}
this.startX = e.clientX
this.startY = e.clientY
},
//截图区域展示后再获取鼠标移动时的坐标
getlastPostion(e){
if(!this.isShowCutScreen) return
this.endX = e.clientX
this.endY = e.clientY
},

# 五、将截图写入 canvas 同时复制至剪切板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<button v-show="isShowSetting" @click="copyToclipboard">复制并关闭</button>
copyToclipboard(){
/*获取物理像素与CSS像素之比,有些设备这个比值会大于一,如果不乘这个值就会出现,截图位置和大小有偏差。相当于将截图区域的图片放大这个系数放在没有放大的canvas中,截图范围变小。*/
const devicePixelRatio = window.devicePixelRatio
let canvas = document.querySelector('canvas')
let ctx=canvas.getContext("2d")
let img=document.querySelector('img')
let startX = this.startX*devicePixelRatio
let startY = this.startY*devicePixelRatio
let endX = this.endX*devicePixelRatio
let endY = this.endY*devicePixelRatio
let width = endX-startX
let height = endY-startY
canvas.width = width
canvas.height = height
ctx.drawImage(img,startX,startY,width,height,0,0,width,height)
//将canvas变成blob对象,然后使用clipboard复制到剪切板中
canvas.toBlob((blob)=>{
navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]).then(()=>{
ipcRenderer.send('closeFullScreen')
}).catch((err)=>console.log(err))
})
}

#

  1. 在 electron 中实现截图
  2. 在 electron 中实现截图
  3. 剪切板使用