龙空技术网

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

Nodejs开发 84

前言:

现在各位老铁们对“vue图片压缩不失真”大约比较着重,看官们都想要知道一些“vue图片压缩不失真”的相关文章。那么小编也在网络上网罗了一些有关“vue图片压缩不失真””的相关资讯,希望同学们能喜欢,兄弟们快快来学习一下吧!

作者:徐小夕 来源:趣谈前端

前言

网页截图功能目前也是非常常见的需求, 尤其是在在线教育领域. 我们朋友圈的微信海报,活动海报等,一般都是运营/市场人员通过设计工具设计而成, 但是如何更好的映射到自己的服务体系里面, 比如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,后面看了该库的源码,感觉写的也很优雅易懂,后期做二次开发应该问题不是很大。我们可以看看其官网的基本使用:

// 引入

import domtoimage from 'dom-to-image';

// 生成图片

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);

});

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

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

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

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

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

上面说的方案都可以尝试, 第三种方案笔者之前也开源过爬虫应用来解决这个问题, 感兴趣的可以研究了解一下, 我们很明显会选择第一种方案来实现, 就如演示中的, 我们看到的弹窗中的H5其实是在iframe中渲染的:

实现思路有了, 该问题也就很好实现了, 我们只需要在父页面和iframe实现消息通信即可, 比如在iframe加载完成之后手动通知iframe截取自身. 基本实现代码如下:

// 编辑器页面, 也就是父页面

// 定义截图页面句柄函数

window.getFaceUrl = (url) => {

setFaceUrl(url)

setShowModalIframe(false)

}

// iframe页面, 也就是预览页面

const generateImg = (cb:any) => {

domtoimage.toBlob(refImgDom.current,

{

width,

height,

}

)

.then(function (blob:Blob) {

const formData = new FormData();

formData.append('file', blob, 'tpl.jpg');

req.post('/files/upload/free', formData).then((res:any) => {

cb && cb(res.url)

})

})

.catch(function (error:any) {

console.error('oops, something went wrong!', error);

});

}

// 触发父页面的方法,将图片传给父页面

generateImg((url:string) => {

parent.window.getFaceUrl(url);

})

标签: #vue图片压缩不失真