前端如何实现一键截图功能?

前言

网页截图功能目前也是非常常见的需求, 尤其是在在线教育领域. 我们朋友圈的微信海报, 活动海报等, 一般都是运营/市场人员通过设计工具设计而成, 但是如何更好的映射到自己的服务体系里面, 比如H5页面中, 植入更多信息收集, 交互能力. 这一块的应用探索, 页面截图是一个非常好的解决方案.

接下来笔者就来复盘一下如何基于网页, 一键生成页面海报的功能, 并将此能力, 集成到笔者的开源项目H5-Dooring中为编辑器赋能.

正文

在实现具体功能之前, 我们先看看具体的实现效果: 从演示中我们可以看出, 我们最终目标是实现在PC端生成H5页面的截图, 所以可能会涉及到以下几个问题:

  • 如何实现将页面转化为图片
  • 如何实现H5效果模拟并截取实际的H5页面

我们可以先来想想实现思路, 如何能基于dom转化为图片? 这块技术也是老生常谈的课题了, 我们都知道可以用canvas来实现, 大致流程如下: 我们如果用原生的实现方案, 大致要经历以上几个步骤, 其中第二步是关键环节也是最复杂的一步, 我们需要手动实现dom到canvas的映射, 最后转化为标准的canvas绘图对象. 当然现成也有很多库可以直接帮我们简化这一步骤, 比如html2canvas, dom-to-image. 接下来我们就来解决第一个问题.

如何实现将页面转化为图片

在亲自调研了html2canvas库并使用的过程中, 笔者发现了很多问题, 比如如果样式中出现%单位, 或者有一些图片背景的问题, 导致html2canvas并没有很好的work, 而且渲染还原度和清晰度都有问题, 所以笔者暂时没有深入研究(不过这些问题可以通过修改库本身解决), 后面笔者直接用了dom-to-image, 发现使用起来很简单, 而且几乎不会出现上面说的这些问题, 所以笔者果断采用了dom-to-image, 后面看了该库的源码, 感觉写的也很优雅易懂, 后期做二次开发应该问题不是很大. 我们可以看看其官网的基本使用:

1// 引入 2import domtoimage from 'dom-to-image'; 3 4// 生成图片 5domtoimage.toPng(node) 6 .then(function (dataUrl) { 7 var img = new Image(); 8 img.src = dataUrl; 9 document.body.appendChild(img); 10 }) 11 .catch(function (error) { 12 console.error('oops, something went wrong!', error); 13 });

用法也很简单, 而且它提供了足够多的配置项, 我们可以灵活配置.

第一个问题就这么解决了, 不过在使用过程中发现图片模糊的问题, 这块网上也有很多解决方案. 比如先放大dom, 在处理成canvas最后生成图片的时候在缩小等, 这块笔者就不一一举例了.

如何实现H5效果模拟并截取实际的H5页面

因为我们设计的H5页面都在pc端完成的, 所以要想生成H5预览图, 无非是本地模拟尺寸, 进行渲染, 具体方案如下:

  • 采用iframe作为H5页面容器去生成截图
  • 直接限制宽度在当前页面生成截图
  • 采用服务端爬虫一键模拟手机访问生成截图

上面说的方案都可以尝试, 第三种方案笔者之前也开源过爬虫应用来解决这个问题, 感兴趣的可以研究了解以下, 我们很明显会选择第一种方案来实现, 就如演示中的, 我们看到的弹窗中的H5其实是在iframe中渲染的: 实现思路有了, 该问题也就很好实现了, 我们只需要在父页面和iframe实现消息通信即可, 比如在iframe加载完成之后手动通知iframe截取自身. 基本实现代码如下:

1// 编辑器页面, 也就是父页面 2// 定义截图子页面句柄函数 3window.getFaceUrl = (url) => { 4 setFaceUrl(url) 5 setShowModalIframe(false) 6} 7 8// iframe页面, 也就是预览页面 9const generateImg = (cb:any) => { 10 domtoimage.toBlob(refImgDom.current, 11 { 12 width, 13 height, 14 } 15 ) 16 .then(function (blob:Blob) { 17 const formData = new FormData(); 18 formData.append('file', blob, 'tpl.jpg'); 19 req.post('/files/upload/free', formData).then((res:any) => { 20 cb && cb(res.url) 21 }) 22 }) 23 .catch(function (error:any) { 24 console.error('oops, something went wrong!', error); 25 }); 26} 27 28// 触发父页面的方法,将图片传给父页面 29generateImg((url:string) => { 30 parent.window.getFaceUrl(url); 31})

最后

以上教程笔者已经集成到H5-Dooring中,对于一些更复杂的交互功能,通过合理的设计也是可以实现的,大家可以自行探索研究。

github地址:H5编辑器H5-Dooring

如果想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在《趣谈前端》一起学习讨论,共同探索前端的边界。

更多推荐

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java将前端的json数组字符串转换为列表

记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang