经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
JS如何实现页面截屏功能实例代码
来源:jb51  时间:2021/6/15 11:27:59  对本文有异议

"页面截屏"是前端经常遇到的需求,比如页面生成海报,弹窗图片分享等,因为浏览器没有原生的截图API,所以需要借助canvas来实现导出图片实现需求。

可行性方案

  1. 方案1: 将 DOM 改写成 canvas ,调用canvas的toBlob或者toDataURL方法即刻上传到七牛云或服务器
  2. 方案2: 使用第三方库html2canvas.js实现 canvas , 在不更改页面已有DOM的情况下优雅生产canvas

解决方案的选择

方案1:需要手动计算每个DOM元素的Computed Style,然后需要计算好元素在canvas的大小位置等属性。

方案1难点

  • 需要弃用已有的html页面,改用canvas重写。
  • 页面结构层复杂的情况下用canvas写,不易重构。
  • 有一定canvas基础。

方案2:该项目在Github上stars已有两万多start,作者仍在积极维护。API非常简单,在已有项目中开箱即用。

html2canvas

因为是常见的需求,所以社区会有成熟的解决方案,首先试试社区的解决方案。

  1. <div id="capture" style="padding: 10px; background: #f5da55">
  2. <h4 style="color: #000; ">Hello world!</h4>
  3. </div>
  1. html2canvas(document.querySelector("#capture")).then(canvas => {
  2. document.body.appendChild(canvas)
  3. });

以上是官网的实例用法。在网页上出现了一个新的 canvas DOM。接下来我们只需要把canvas转换成图片就好。这里使用canva原生的toDataURL和toBlob方法上次到七牛云。

使用时需要注意。此处如果生产的画布中有跨域图片,需要配置allowTaint为true。

如果是原生canvas实现,canvas需要所有跨域图片请求完成才可绘制。有两种解决方案

  • 方案1:在html上写好img标签,src写好对应的图片url。缺点很明显,会污染页面的布局结构。
  • 方案2:使用js,使用new Image()的方式。设置src到对应的图片url,在onload回调中处理相关操作。优点:可行性最高,不过有回调地狱的问题。我们用Promise改写一下
  1. function asyncImage(url) {
  2. const img = new Image();
  3. img.src = url;
  4. img.setAttribute('crossOrigin', 'anonymous');
  5. return new Promise((resolve, reject) => {
  6. img.onload = () => resolve(img);
  7. img.onerror = reject;
  8. });
  9. }

好的,大功告成~是不是可以交付需求了呢?开开心心提测,但是在移动端测试的时候发现生产的图片非常模糊。这样是不行的,明显low了许多(测试不给过orz)。

github有相应的解决方案 传送门 ,这个回答也是解决很多人的问题

基本原理:将canvas宽高放大两倍。把css把canvas的style设置成1倍大小。

  1. var shareContent = YourTargetElem;
  2. var width = shareContent.offsetWidth;
  3. var height = shareContent.offsetHeight;
  4. var canvas = document.createElement("canvas");
  5. var scale = 2 || window.devicePixelRatio ; //也可以使用设备像素比
  6.  
  7. canvas.width = width * scale;
  8. canvas.height = height * scale;
  9. canvas.getContext("2d").scale(scale, scale);
  10.  
  11. var opts = {
  12. scale: scale,
  13. canvas: canvas,
  14. logging: true,
  15. width: width,
  16. height: height
  17. };
  18. html2canvas(shareContent, opts).then(function (canvas) {
  19. var context = canvas.getContext('2d');
  20.  
  21. var img = Canvas2Image.convertToImage(canvas, canvas.width, canvas.height);
  22.  
  23. document.body.appendChild(img);
  24. $(img).css({
  25. "width": canvas.width / 2 + "px",
  26. "height": canvas.height / 2 + "px",
  27. })
  28. });

原理我们已经知道了,实际操作之后图像也确实清晰了很多。但是问题还是没有解决掉。

缩小虽然提高了清晰度,但是我们需要的图片是原始比例的大小。。

最终多次尝试无果后,选择放弃使用框架。直接用原生canvas撸一个!

canvas绘制

我们知道,在高清屏的设备下,任何绘制canvas中的图像、文字、线条、形状都可能会出现模糊的问题。可通过引入 GitHub 中的 hidpi-canvas 有效地解决。

  1. 首先去 GitHub 下载 hidpi-canvas.js 文件:传送门
  2. 在项目中引入 hidpi-canvas.js 文件;
  3. 调用 getPixelRatio() 函数,得到 ratio 值;
  4. 在 drawImage() 中,将 width 和 height 乘以 ratio;
  5. 最终的canvas导出为Blog,转换成文件对象上传七牛云。

核心代码如下

  1. function asyncImage(url) {
  2. const img = new Image();
  3. img.src = url;
  4. img.setAttribute('crossOrigin', 'anonymous');
  5. return new Promise((resolve, reject) => {
  6. img.onload = () => resolve(img);
  7. img.onerror = reject;
  8. });
  9. }
  10. async function drawCanvas(){
  11. var canvas = document.querySelector('canvas');
  12. var context = canvas.getContext('2d');
  13. var ratio = getPixelRatio(context); // 关键代码
  14. canvas.width = 300 * ratio; // 画布宽度
  15. canvas.height = 300 * ratio; // 画布高度
  16. var divWidth = 300 * ratio; // 用于内容居中
  17. var divHeight = 300 * ratio; // 用于内容居中
  18. const image = await asyncImage('picUrl')
  19. const imgWidth = 550
  20. const imgHeight = 300
  21. context.drawImage(this, 50, 50, imgWidth * ratio, imgHeight * ratio)
  22. // Some other code
  23. const Blob = canvas.toBlob((Blob)=>{
  24. //上传七牛云
  25. });
  26. }

最终生成的图片终于清晰了...只需要根据dom的offsetWidth等适配不同屏幕就可以了。

总结

如果对图片的清晰度要求不高,或者图片需求是生成缩略图的情况下。采用 html2canvas 是非常不错的选择。
否则,还是用canvas绘制出的图片更清晰。

到此这篇关于JS如何实现页面截屏功能的文章就介绍到这了,更多相关JS页面截屏功能内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号