likaia / js-screen-shot

web端自定义截图插件(原生JS版)
https://www.kaisir.cn/js-screen-shot/
MIT License
769 stars 106 forks source link
electron javascript js-screen-shot screenshot typescript web-screenshot

js-web-screen-shot · npm yarn github

web端自定义截屏插件(原生JS版),运行视频:实现web端自定义截屏功能 ,效果图如下:截屏效果图

写在前面

关于此插件的更多介绍以及实现原理请移步:

文档请移步官网

插件安装

yarn add js-web-screen-shot

# or

npm install js-web-screen-shot --save

插件使用

由于插件采用原生js编写且不依赖任何第三方库,因此它可以在任意一台支持js的设备上运行。

注意⚠️: 如果需要使用插件的webrtc模式或者截图写入剪切板功能,需要你的网站运行在https环境或者localhost环境。当然,也可以通过修改浏览器设置的方式实现在所有环境下都能运行。步骤如下: 1.打开谷歌浏览器,在地址栏输入chrome://flags/#unsafely-treat-insecure-origin-as-secure 2.在打开的界面中:下拉框选择enabled,地址填写你的项目访问路径。 img.png

import形式使用插件

electron环境下使用插件

由于electron环境下无法直接调用webrtc来获取屏幕流,因此需要调用者自己稍作处理,具体做法如下所示:

// 修复electron18.0.0-beta.5 之后版本的BUG: 无法获取当前程序页面视频流 const selfWindws = async () => await Promise.all( webContents .getAllWebContents() .filter(item => { const win = BrowserWindow.fromWebContents(item); return win && win.isVisible(); }) .map(async item => { const win = BrowserWindow.fromWebContents(item); const thumbnail = await win?.capturePage(); // 当程序窗口打开DevTool的时候 也会计入 return { name: win?.getTitle() + (item.devToolsWebContents === null ? "" : "-dev"), // 给dev窗口加上后缀 id: win?.getMediaSourceId(), thumbnail, display_id: "", appIcon: null }; }) );

// 获取设备窗口信息 ipcMain.handle("IPC消息名称", async (_event, _args) => { return [ ...(await desktopCapturer.getSources({ types: ["window", "screen"] })), ...(await selfWindws()) ]; });


* 渲染线程(前端)发送消息封装处理(相应写法自己调整)
```typescript
// xxx.ts
export const getDesktopCapturerSource = async () => {
  return await window.electron.ipcRenderer.invoke<Electron.DesktopCapturerSource[]>("IPC消息名称", []);
}

export const doScreenShot = async ()=>{ // 下面这两块自己考虑
const sources = await getDesktopCapturerSource(); // 这里返回的是设备上的所有窗口信息 // 这里可以对sources数组下面id进行判断 找到当前的electron窗口 这里为了简单直接拿了第一个 const stream = await getInitStream(sources[0]);

new ScreenShot({ enableWebRtc: true, // 启用webrtc screenFlow: stream!, // 传入屏幕流数据 level: 999, }); }

> 感谢 [@Vanisper](https://github.com/Vanisper) 提供的在electron环境下使用本插件的兼容思路。

### electron示例代码
如果你看完上个章节的使用方法,依然不是很理解的话,这里准备了一份在electron环境下使用本插件的demo,请移步[electron-js-web-screen-shot-demo](https://github.com/Vanisper/electron-js-web-screen-shot-demo)。

### 兼容移动端
插件对触屏设备做了兼容处理,如果你是pc端的触屏设备可以支持webrtc模式,如果是移动端那么就只能使用html2canvas模式。
```javascript
import ScreenShot from "js-web-screen-shot";

const config = {
    enableWebRtc: false
};
const screenShotHandler = new ScreenShot(config);
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<!--禁止移动端浏览器的缩放-->
<meta name="viewport" content="user-scalable=no">
</head>
<body>
/body>
</html>

注意:在移动端使用时,需要在head标签里禁止浏览器的缩放行为,否则就会出现在使用撤销功能时,多次双击造成界面放大问题。

Vue项目下使用乱码问题

当你vue项目中使用h2c模式进行截图时,画布左上角可能会出现一些奇怪的字符,这是由于noscript标签导致的,将其删除即可。

参数说明

截图插件有一个可选参数,它接受一个对象,对象每个key的作用如下:

使用当前标签页进行截图相对而言用户体验是最好的,但是因为chrome 112版本的bug会造成页面内容挤压导致截取到的内容不完整,因此只能采用其他方案来解决此问题了。wrcWindowModehiddenScrollBar都可以解决这个问题。

  • wrcWindowMode方案会更完美些,但是用户授权时会出现其他的应用程序选项,用户体验会差一些
  • hiddenScrollBar方案还是采用标签页截图,但是会造成内容挤压,底部出现空白。

两种方案的优点与缺点讲完了,最好的办法还是希望chrome能在之后的版本更新中修复此问题。

上述类型中的?:为ts中的可选类型,意思为:这个key是可选的,如果需要就传,不需要就不传。

imgSrc是url时,如果图片资源跨域了,必须让图片服务器允许跨域才能正常加载。同样的loadCrossImg设置为true时,图片资源跨域了也需要让图片服务器允许跨域。

快捷键监听

插件容器监听了三个快捷键,如下所示:

额外提供的API

插件暴露了一些内部变量出来,便于调用者根据自己的需求进行修改。

getCanvasController

该函数用于获取截图容器的DOM,返回值为HTMLCanvasElement类型。

示例代码:

import ScreenShot from "js-web-screen-shot";

const screenShotHandler = new ScreenShot();
const canvasDom = screenShotHandler.getCanvasController();

注意:如果截图容器尚未加载完毕,获取到的内容可能为null。

destroyComponents

该函数用于销毁截图容器,无返回值。

示例代码:

import ScreenShot from "js-web-screen-shot";

const screenShotHandler = new ScreenShot();
screenShotHandler.destroyComponents()

completeScreenshot

该函数用于将框选区域的截图内容写入剪切版,无返回值。

该方法可以跟cropBoxInfo参数结合起来实现指定位置的自动截图,截图内容默认写入剪切版内,如果你想拿到截取到的base64内容可以通过completeCallback参数拿到,或者直接从sessionStorage中获取。

该回调函数中返回的参数格式如下所示:

示例代码:

      const plugin = new screenShotPlugin(
        {
          clickCutFullScreen:true,
          wrcWindowMode: true,
          cropBoxInfo:{x:350, y:20, w:300, h:300},
          completeCallback: ({base64, cutInfo}) => {
            console.log(base64, cutInfo);
          },
          triggerCallback:() => {
            // 截图组件加载完毕调用此方法来完成框选区域的截图
            plugin.completeScreenshot()
          }
        });

注意:此方法在1.9.9版本之后不再返回字符串类型的数据,而是返回的对象格式。

工具栏图标定制

如果你需要修改截图工具栏的图标,可以通过覆盖元素css类名的方式实现,插件内所有图标的css类名如下所示:

square为例,要修改它的图标,只需要将下述代码添加进你项目代码的样式中即可。

  .square {
    background-image: url("你的图标路径") !important;

    &:hover {
      background-image: url("你的图标路径") !important;
    }

    &:active {
      background-image: url("你的图标路径") !important;
    }
 }

写在最后

至此,插件的所有使用方法就介绍完了,该插件的Vue3版本,请移步:vue-web-screen-shot