页面截屏是前端经常遇到的需求,比如页面生成海报,弹窗图片分享等,我来为大家科普一下关于各个浏览器全屏截图?下面希望有你要的答案,我们一起来看看吧!

各个浏览器全屏截图(浏览器截图方案分析)

各个浏览器全屏截图

浏览器截图方案分析

页面截屏是前端经常遇到的需求,比如页面生成海报,弹窗图片分享等。

以下是我整理三种截图方案:

  1. HTMl2Canvas
  2. DOM-to-image
  3. webRTC
html2canvas

html2canvas 用的比较广泛的前端截图方案,先将 DOM 一个个 转为 Canvas 然后导出图片(使用 canvas 自带的 toDataUrl、toBobl)即可。使用起来应该是兼容性比较好的方案了,能解决大部分的需求,但是也有一些小问题,如:

  1. 图片跨域,开启
  2. css 属性错乱
  3. 遇到 canvas 元素导出后为透明色。

大部分问题还是可以通过配置和百度解决的

const getDomImg = (eleId) => { html2canvas(document.getElementById(eleId), { //superMap整个页面的节点 backgroundColor: null, //画出来的图片有白色的边框,不要可设置背景为透明色(null) allowTaint: true, useCORS: true, //支持图片跨域 scale: 1, //设置放大的倍数 }) .then((canvas) => { //截图用img元素承装,显示在页面的上 let img = new Image(); img.src = canvas.toDataURL("image/jpg"); // toDataURL :图片格式转成 base64 // 直接下载 let a = document.createElement("a"); a.href = canvas.toDataURL("image/jpeg"); a.download = "test"; a.click(); }) .catch((err) => { console.log("html2canvas err", err); }); };

dom-to-image

使用 svg,通过 createObjectURL 或 encodeURIComponent 处理 svg 得到图像资源,可以把 svg 绘制到 canvas。

dom-to-image-more 是dom-to-image的升级版 将 HTMl 放到 SVG 里,然后创建一个以 SVG 作为源的 Image 元素

但是也有一些问题如: svg 中不允许外部资源(js,css,img 的 url 等),svg 中不支持执行 js,需要经过处理,也不能完全还原

const getDomImg = (eleId) => { domtoimage .toPng(document.getElementById(eleId)) .then(function (dataUrl) { let a = document.createElement("a"); a.href = dataUrl; a.download = "test"; a.click(); }) .catch(function (error) { console.error("生成失败", error); }); };

webRTC

使用浏览器原生 API——webERT中的getDisplayMedia可以将窗口中的资源以录屏方式从其中拿出一帧,但是需要用户授权和做一些窗口选择,相比于前两种方案做不到默认截图。

但是优势也很明显,就是不会有什么样式错乱、图片跨域等问题。因为使用的浏览器原生方法,基本上用户看到是什么样子,截图出来就是什么样子,1: 1 还原。

function getDomImg(videoId: string) { const videoElem: any = document.getElementById(videoId); const displayMediaOptions = { audio: false, video: { width: window.screen.width, height: window.screen.height }, // cursor: "always" }; navigator.mediaDevices .getDisplayMedia(displayMediaOptions) .then((stream) => { videoElem.srcObject = stream; setTimeout(() => { var canvas = document.createElement("canvas"); canvas.width = videoElem.clientWidth; canvas.height = videoElem.clientHeight; canvas .getContext("2d") .drawImage( videoElem, 0, 0, window.screen.width, window.screen.height, 0, 0, canvas.width, canvas.height ); var dataURL = canvas.toDataURL("image/webp"); let a = document.createElement("a"); a.href = dataURL; a.download = "test"; a.click(); let tracks = videoElem.srcObject.getTracks(); tracks.forEach((track) => track.stop()); videoElem.srcObject = null; }, 200); }) .finally(() => {}); }

需要在代码中放入一个 Video 标签

<video id="video"></video>

截图后上传

如果有将截图上传的需求,可以转换一个格式在上传。

canvas 导出的 base64 是不可以直接上传到服务器的,所以需要转一下格式,我这边找了转换 Blob 和 File 两种格式的方法。我用的将图片转为 Blob后上传的。

  1. base64转化为Blob对象

// function convertBase64ToBlob(imageEditorBase64) { var base64Arr = imageEditorBase64.split(","); var imgtype = ""; var base64String = ""; if (base64Arr.length > 1) { //如果是图片base64,去掉头信息 base64String = base64Arr[1]; imgtype = base64Arr[0].substring( base64Arr[0].indexOf(":") 1, base64Arr[0].indexOf(";") ); } // 将base64解码 var bytes = atob(base64String); //var bytes = base64; var bytesCode = new ArrayBuffer(bytes.length); // 转换为类型化数组 var byteArray = new Uint8Array(bytesCode); // 将base64转换为ascii码 for (var i = 0; i < bytes.length; i ) { byteArray[i] = bytes.charCodeAt(i); } // 生成Blob对象(文件对象) return new Blob([bytesCode], { type: imgtype }); }

  1. base64 转 formData

function base64ToFile(data, fileName) { const dataArr = data.split(","); const byteString = atob(dataArr[1]); const options: any = { type: "image/jpeg", endings: "native", }; const u8Arr = new Uint8Array(byteString.length); for (let i = 0; i < byteString.length; i ) { u8Arr[i] = byteString.charCodeAt(i); } let formData = new FormData(); let fileOfBlob = new File([u8Arr], fileName ".jpg", options); //返回文件流 formData.append("file", fileOfBlob); console.log("file", formData); debugger; return formData; }

示例

GitHub:https://github.com/AnsonZnl/w...

代码基于 Create React App 演示三种截图方法的基本使用方式。

参考

javascript

,