关于网站截图功能的几种方案

HTML2canvas

该脚本通过读取 DOM 以及应用于元素的不同样式,将当前页面呈现为 canvas 图像。
它不需要来自服务器的任何渲染,因为整个图像是在客户端上创建的。但是,由于它太依赖于浏览器,因此该库不适合在 nodejs 中使用。它也不会神奇地规避任何浏览器内容策略限制,因此呈现跨域内容将需要代理来将内容提供给相同的源。
该脚本仍然处理非常实验状态,因此不建议在生产环境中使用它,也不建议使用它来构建应用程序,因为仍然会有重大更改。
该库应该可以在以下浏览器上正常工作
● Firefox 3.5+
● Google Chrome
● Opera 12+
● IE9+
● Edge
● Safari 6+
由于需要手动构建每一个 CSS 属性以支持,因此还有许多尚不支持的属性。

使用方法

// 安装
npm install html2canvas

// 引入
import html2canvas from 'html2canvas'
// 使用
html2canvas(document.body).then(function(canvas) {
  document.body.appnedChild(canvas)
})

中文文档

https://allenchinese.github.io/html2canvas-docs-zh-cn/

缺陷

会有dom样式还原和img的同源策略的问题

dom-to-image与dom-to-image-more

dom-to-image-more是dom-to-image的升级版
dom-to-image-more是一个库,它可以将任意 DOM 节点(包括同源和 blob iframe)转换为用 JavaScript 编写的矢量(SVG)或光栅(PNG 或 JPEG)图像。

使用方法

// 安装
npm install dom-to-image-more
// 引入
/* in ES 6 */
import domtoimage from "dom-to-image-more";
/* in ES 5 */
var domtoimage = require("dom-to-image-more");
// 使用
var node = document.getElementById("my-node");
domtoimage
  .toPng(node)
  .then(function (dataUrl) {
    var img = new Image();
    img.src = dataUrl;
    document.body.appendChild(img);
  })
  .catch(function (error) {
    console.error("oops, something went wrong!", error);
  });

文档

https://www.npmjs.com/package/dom-to-image-more

缺陷

也有样式还原不完全或者不正确问题,但是比html2canvas优一些

使用 navigator.mediaDevices.getDisplayMedia() API

  1. 这个 MediaDevices 接口的 getDisplayMedia()方法提示用户去选择和授权捕获展示的内容或部分内容(如一个 窗口)在一个MediaStream 里。 然后,这个媒体流可以通过使用 MediaStream Recording API 被记录或者作为WebRTC 会话的一部分被传输。

  2. 这个api返回的屏幕视频流可以被用于video标签来进行播放,然后video又可以通过canvas的context的drawImage方法绘制一帧作为canvas的页面。

  3. 随后使用canvas.toDataURL绘制成base64的图像数据。 这个数据可以通过种种方式进行使用。

  4. 下面还提供了将base64转变为File对象的方法,以及保存到浏览器临时url的办法

使用方法

// 容器
let imgFile,imgUrl

// 点击进行截图
function leaderHandler() {
	// 创建标签
  const video = document.createElement('video')
  // 自动播放
  video.setAttribute('autoplay', 'autoplay')
  // 静音
  video.setAttribute('muted', 'muted')

  startCapture(function (screen) {
    video.srcObject = screen
  })
  video.addEventListener('loadeddata', function () {
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    // 设置一个宽高
    canvas.width = 1280
    canvas.height = 773
    if (!ctx) return
    setTimeout(() => {
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
      let base64 = canvas.toDataURL('image/png')
      // 转为File对象  
      imgFile = base64ImgtoFile(base64)
      // HACK 创建的地址 可以通过revokeObjectURL()清除以释放内存 是个优化点
      imgUrl = window.webkitURL.createObjectURL(img) || window.URL.createObjectURL(img)
      // 停止以释放内存和停止分享流
      let tracks = video.srcObject.getTracks()
      tracks.forEach((track) => track.stop())
      video.srcObject = null
    }, 250)
  })
}


// 开启视频流截屏
async function startCapture(success) {
  var constraints = {
    audio: false,
    video: true,
    width: 1280,
    height: 773
  }
  if (navigator.mediaDevices?.getDisplayMedia) {
    navigator.mediaDevices.getDisplayMedia(constraints).then(success)
  } else {
    ;navigator.getDisplayMedia(constraints).then(success)
  }
}
// base64 转file对象
function base64ImgtoFile(data, filename = 'file') {
  const arr = data.split(',')
  const mime = arr[0].match(/:(.*?);/)[1]
  const suffix = mime.split('/')[1]
  const bstr = atob(arr[1])
  let n = bstr.length
  const u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], `${filename}.${suffix}`, {
    type: mime
  })
}

缺陷

需要用户同意权限,部分设备需要做兼容性处理
有模糊的问题,不能做到完全清晰,但是也有对应缓解方案。
缓解不太清晰的方案
canvas标签,将width和height标签属性扩大一倍,然后通过css将样式上的width和height规定成正确的样式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值