前言
HTML5是HTML最新的修订版本,设计目的是为了在移动设备上支持多媒体, 以便为我们呈现更丰富的页面表现. HTML5 还是跨平台的,被设计为在不同类型的硬件(PC、平板、手机、电视机等等)之上运行。因此衍生出不同场景下的应用, 比如移动端官网, H5活动页, H5营销页等. 随着互联网对的发展, 在大数据领域中的移动端BI模型, 也可以用H5来承载.
为了满足以上需求, 已经有很多企业开始搭建H5编辑平台, 比如说某秀, 某展, 笔者之前也开源了自己的H5编辑器H5-Dooring, 以方便企业快速搭建满足业务场景的H5页面.
我们都知道要想设计一款好用的H5编辑器, 一定要简化用户操作, 将用户的使用成本降低到极致, 要想实现这一标准, 我们需要具备以下条件:
- 丰富的组件库
- 丰富的图片资源
- 灵活的组件配置
- 傻瓜式操作
- 开箱即用的H5页面模版(模版库)
以上5个条件是开发H5编辑器非常重要的参考指标, 前四个条件笔者在之前的文章中都有具体的实现方案, 笔者将具体介绍H5编辑器中的模版库功能实现, 希望能给同样需要此需求的IT工程师们有个参考.
章节概要
- H5编辑器中的模版库设计基本思路
- 如何实现iframe子页面和父页面通信
- 基于dom元素自动生成封面图解决方案
正文
作为一名前端工程师, 解决项目问题是我们的基本职责之一, 我们可以利用已掌握的知识去解决项目开发中的问题和需求, 这也是我们职业生涯必将经历的第一个阶段,即——适应期. 如果我们想继续晋升, 我们就需要不断的打怪升级,掌握各种技能, 这样我们才能在未来遇到问题时采用最佳的方案高效的解决问题, 也就是第二个阶段——发展期.
接下来笔者将一步步带大家完成H5编辑器中的模版库并实现自动生成封面图方案, 大家需要掌握前端工程师需要具备的基本能力: javascript,html5以及模块化的开发方式(es6的模块化以及如何是使用第三方模块).
H5编辑器的模版库设计基本思路
我们都知道H5编辑器中的页面呈现大多是基于json schema, 每一个在组件我们都可以细化为一个json元数据, 这样做是为了我们能更细粒度的控制组件, 而模版, 即是由很多组件组合而成的区块或者完整的页面, 对应的就是json元数组. 所以对应的方案就是我们给用户提供一个保存模版的按钮, 当用户点击保存之后我们只需要拿到当前配置的json数据, 保存到对应的数据库中即可. 数据结构大致如下:
[
{
"id": "12reg2",
"name": "趣谈前端落地页",
"tpl": [...组件配置数据项]
},
{
"id": "12rdg5",
"name": "H5-Dooring落地页",
"tpl": [...组件配置数据项]
}
]
我们在数据库中取出以上数据直接用react或者vue来渲染出来即可. 至于如何拿到json数据, 可参考H5-Dooring的具体实现流程.
但是光实现保存数据还远远不够, 用户在存储了自己的模版之后, 如果后面想直接使用之前配置的模版, 那么如何快速找到呢? 我们虽然可以通过模版的name来识别不同的模版, 但是一旦模版越来越多, 用户单纯从模版名称还是不能很方便的选出自己想要的模版, 所以这个时候我们往往期望 H5编辑器 能提供模版预览图的功能. 如下所示: 所以我们又遇到一个难题, 就是如何生成模版预览图.
如何生成模版预览图
生成模版预览图的常规思路就是基于我们的预览页面, 生成预览页面截图, 然后存储到对应模版数据中.步骤如下: 所以说用户需要在H5编辑器的编辑页面先配置H5模版, 然后跳到预览页面, 基于预览页面生成预览截图, 最后再跳回编辑页面保存. 这一过程对于用户来说不太友好, 因为涉及到不同页面的相互跳转, 我们可以进一步优化, 在编辑页面直接生成预览图片, 为了实现这一逻辑, 我们有两种方案:
- 通过服务端请求预览页面, 在服务端生成页面截图然后和模版数据一起存储入库
- 通过canvas + iframe技术基于dom前端生成预览图片
由于前者实现过程比较复杂, 需要借助如puppeteer之类的库, 而且还要保持图片和模版数据的同步,所以笔者建议选择第二种方案, 纯前端实现. 笔者将在接下来的内容中一一介绍.
如何实现iframe子页面和父页面通信
在上文的介绍中我们选择了使用canvas + iframe技术来实现页面截图, 我们先来看看实现效果: 由上图可知 我们提供给用户两种设置封面的方法: 使用默认图片, 自动生成封面.
用户可以用Dooring提供的默认封面也可以直接使用生成的预览封面.图二中其实弹窗内是iframe, 笔者设计了一种机制使得iframe内容渲染完成之后自动截图上传给服务端, 然后iframe和父页面通信将图片url传给编辑页面, 之后和模版数据一起保存. 要想实现页面父子通信, 我们就需要了解iframe如何和父页面交互. 关于父子页面通信的详细介绍,可以参考 笔者的记一次老项目中的跨页面通信问题和前端实现文件下载功能. 这里我们来看看iframe 如何和父页面通信:
// iframe点用副页面函数
parent.window.getFaceUrl(url);
// 父页面定义的全局函数
window.getFaceUrl = (url) => {
setFaceUrl(url)
setShowModalIframe(false)
}
以上我们就基本攻克了父子传值以及整个流程设计方案, 由于具体细节非常多, 比如如何存储数据, 如何整合数据到模版, 可以在笔者的H5-Dooring项目中学习了解.
基于dom元素自动生成封面图解决方案
上面基本实现了整个模版库的保存流程, 接下来我们实现保存预览图片的细节.由于我们是基于页面元素生成预览图, 所以需要前端能将dom转化为图片, 这里笔者调研了2个比较知名的库:
- html2canvas
- dom-to-image
因为html2canvas现在还处于实验阶段, 而且笔者身边盆友用欧之后确实有写不可描述的bug,笔者分析了dom-to-image, 基本能满足目前的需求,所以我们直接用它来实现.
我们要得到上文中实现的流程, 即需要将dom转化为图片, 然后发送给服务器, 最后拿到服务器返回的图片地址, 最后将图片地址和模版数据一起保存. 我们直接先看代码:
import domtoimage from 'dom-to-image';
// ...其他库
// 将dom转化为图片逻辑
const generateImg = (cb) => {
domtoimage.toBlob(ref.current)
.then(function (blob) {
const formData = new FormData();
formData.append('file', blob, 'tpl.jpg');
req.post('/files/xxx/xxx', formData).then((res) => {
cb && cb(res.url)
})
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
}
之后的步骤就非常简单了, 拿到图片url传给父页面用来展示和保存.
H5编辑器H5-Dooring更新说明
以上教程笔者已经集成到H5-Dooring中,对于一些更复杂的交互功能,通过合理的设计也是可以实现的,大家可以自行探索研究。
github地址:H5在线编辑器H5-Dooring
由于H5-Dooring还在不断更新迭代, 笔者将具体介绍一下更新内容:
- H5编辑器整体界面重构:
- 添加图片库功能:
- 可视化数据源编辑功能:
- 模版库实现:
- 预览界面优化:
最后
如果想学习更多H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在《趣谈前端》一起学习讨论,共同探索前端的边界。