如何实现H5可视化编辑器的实时预览和真机扫码预览功能

8,770 阅读7分钟

前言

所见即所得的设计理念在WEB IDE领域里一直是备受瞩目的功能亮点, 也能极大的提高** web coder的编程体验和编程效率. 笔者接下来就将对H5可视化编辑器实时预览真机扫码预览**功能做一次方案剖析, 为大家在设计类似产品的时候提供一些思路.

我们还是基于笔者开发的 H5-Dooring可视化编辑器作为案例来分析上述功能实现.

你将收获

  • 实时预览的应用场景和实际案例
  • 画布元素和属性编辑器的实时联动方案
  • 实时预览的一般思路
  • 真机扫码预览的实现思路
  • 基于nodejs中间层实现高可用的实时预览方案

正文

一般情况下实时预览的功能会交给前端来实现, 比如我们经常看到的微信开发者工具的预览, 支付宝小程序的预览, vscode的预览插件, 比较经典的DW也是集成了强大的实时预览功能, 接下来我们看一个H5-Dooring的在线编程的实时预览模块:

H5页面可视化搭建平台中, 我们也希望能实时的看到我们配置页面的效果, 比如改变了某个属性,能在画布中实时生效, 还能在手机上查看真机效果, 提供这一实时预览功能无疑是可视化配置平台的刚需. 如下案例: PC端模拟手机预览效果: 真机预览入口和效果:

所以我们设计实时预览的关键就在于如何高保真的去还原用户在画布中的配置, 让误差和体验做到极致.

接下来笔者将具体介绍如何实现以上几种预览方式,以及如何设计一款高可用的预览方案.

1. 画布元素和属性编辑器的实时联动方案

画布元素和属性编辑器的实时联动方案主要指的是属性编辑器的修改如何实时同步到画布元素中, 抽象为下图概念: 要想实现右边的属性编辑器修改了内容, 画布上能实时更新改动, 我们呢需要实现一种模式, 让左右两边相关联, 也就是“联动”的概念. 我们都知道, 每个可视化组件都对应一个唯一的schema(在H5-Dooring的文章中已经介绍过,感兴趣的朋友可以学习了解), schema的结构类似如下:

{
	"config": {
    	"color": "#fff",
        "name": "徐小夕"
    },
    "editData": [
    	{
        	"type": "Text",
            "key": "name"
        },
        {
        	"type": "Color",
            "key": "color"
        }
    ]
}

一旦设计了这样的数据结构, 我们就可以实现动态渲染编辑器的表单(通过editData), 并且将修改的值同步给组件(通过editData -> config的映射关系).

其次我们需要定义好共享数据源, 我们可以用vuex(比如你是vue技术栈),或者dva(如果你是react技术栈), 大致设计思路如下: 本质上就是在属性编辑器里触发action, 修改对应组件的config, 然后差量更新画布内容. pointData是画布上组件的数据集, 用来展示H5页面以及动态渲染属性编辑器的编辑项. 后面我们介绍的预览功能也依赖于pointData提供的数据.

2. 实时预览的一般思路

在笔者之前的文章中详细的介绍了如何实现Web IDE的实时预览方案, 也就是nodejs + iframe的方式, 但是对于我们H5-dooring可视化编辑器来说, 可能需要另一种方式, 也就是用户在需要预览的时候可以手动去模拟真机预览或者真机预览, 这里我们通常会在编辑器界面里提供预览按钮, 当用户点击时可以跳到预览视图,如下: 基于我们之前提到的json schema作为预览的数据源, 我们很容易想到在预览页面通过数据源来重新渲染出一个H5页面, 思路如下: 预览页面如果是新开页面, 比如H5-Dooring的实现方式, 那么这个数据源需要在预览之前存储到localStorage中, 由于localStorage的特性我们可以在同域下跨页面共享数据,所以很方便实现我们的需求. 至于render engine部分, 我们只需要使用react-grid-layout提供的数据供给方案即可.代码如下:

<GridLayout
  className={styles.layout}
  cols={24}
  rowHeight={2}
  width={vw > 800 ? 375 : vw}
  margin={[0, 0]}
>
  {pointData.map((value: PointDataItem) => (
    <div className={styles.dragItem} key={value.id} data-grid={value.point}>
      <DynamicEngine {...(value.item as any)} />
    </div>
  ))}
</GridLayout>

至于DynamicEngine的实现, 可以看笔者的H5-Dooring源码来了解具体实现过程. 但是单纯采用localstorage的方案会存在一些问题, 在接下来的章节中笔者会详细说明.

3. 真机扫码预览的实现思路

真机扫码预览的实现方案, 笔者简单总结如下图所示: 以上流程中之所以要走nodejs服务是因为手机端需要和PC端配置建立关联才能实现真机预览,这个关联可以是通过url参数, 也可以是url参数+请求的模式, 这里由于配置数据比较大,所以采用后者来实现, url参数用来定位资源路径, 然后在H5母版工程中根据参数请求具体的数据来呈现页面.这也是目前流行的真机预览方案. 我们可以采用qrcode来动态生成二维码, 二维码的形式如下:

const url = `${window.location.protocol}//${window.location.host}/h5_plus/preview?tid=${tid}`

其他至于如何用nodejs返回指定参数的文件, 这个比较简单, 这里就不一一实现了, 但是一定要理解以上的真机预览实现流程.

4. 基于nodejs中间层实现高可用的实时预览方案

在笔者之前写的通过localStroage实现预览数据共享的方案中存在一些缺陷,比如说A用户想把自己通过H5-Dooring配置的H5页面分享给B用户看, 由于存在于两台不同的电脑, B用户是无法获取预览数据的, 进而无法查看他人配置的H5页. 还有一种情况是用户开启了浏览器的无痕模式, 这样在预览页面可能也无法预览, 所以针对这两种场景, 我们有必要做出一些优化来让我们的实时预览具有更高的可用性.

那么如何实现在用户无法正常利用localStroage的情况下仍然能访问我们的配置页面呢? 答案是通过api请求.我们再次利用nodejs来实现存储用户配置的数据, 在预览的时候判断如果localStroage可以获取到数据, 那么直接使用localStroage的数据, 如果获取不到, 直接访问api请求.逻辑大致如下: 以上实现虽然简单, 但是通过如上优化可以提供预览的可用性和体验, 大家在设计产品功能的时候可以参考借鉴.

5. 总结

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

github地址:H5在线编辑器H5-Dooring

最后

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

更多推荐