如何设计H5编辑器中的模版库并实现自动生成封面图

往期精选

  • H5编辑器的图片上传和图片库设计方案

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

  • 在线IDE开发入门之从零实现一个在线代码编辑器

  • 基于React+Koa实现一个h5页面可视化编辑器-Dooring

  • TS核心知识点总结及项目实战案例分析

前言

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还在不断更新迭代, 笔者将具体介绍一下更新内容:

  1. H5编辑器整体界面重构: 

  2. 添加图片库功能: 

  3. 可视化数据源编辑功能: 

  4. 模版库实现: 

  5. 预览界面优化: 

最后

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

评论区

笔者将在下期举行有奖送书活动, 赶快说出你心中的那本书吧~

<think>好的,用户想要在现有的旅游攻略页面上添加一个“添加攻略”功能,且使用Bootstrap5的模态框来实现。首先,我需要确认现有的代码结构,看看在哪里添加按钮和模态框比较合适。 首先,用户提供的代码里有一个分类筛选部分和一个加载更多按钮。根据常规布局,通常在标题旁边或者操作区域放置添加按钮比较合理。比如在分类筛选的右边,也就是现有的下拉菜单旁边添加一个“添加攻略”的按钮,这样用户容易找到。 接下来,需要使用Bootstrap5的模态框组件。记得Bootstrap的模态框需要特定的HTML结构,包括modal、modal-dialog、modal-content等类,以及相关的data属性来触发显示。同时,表单的设计要符合需求,可能需要标题、分类选择、内容、片上传等字段。 然后,考虑表单的提交逻辑。用户可能需要JavaScript来处理表单数据,比如收集输入的值,验证是否填写完整,特别是分类选择部分需要用下拉菜单,且必填。片上传可能需要用到文件输入元素,但后端处理部分这里可能不需要涉及,只需前端展示。 另外,动态生成的攻略卡片部分,在用户提交表单后,可能需要在前端临时显示新添加的攻略,或者重新加载数据。不过根据用户当前的需求,可能只需要前端展示添加的功能,实际的数据保存可能需要后端接口,但用户可能只需要前端部分,所以暂时用JavaScript模拟添加操作,比如将新攻略添加到攻略容器的最前面。 还需要注意按钮的样式,使用Bootstrap的类,比如btn-primary,确保和现有样式一致。标部分使用Font Awesome的加号标,保持统一。 最后,测试一下模态框是否能正常显示和关闭,表单提交后是否清空输入字段,是否有基本的验证提示,比如必填字段的提示。可能还需要在提交后关闭模态框,给出成功提示。 总结步骤:添加按钮触发模态框,构建模态框的表单结构,处理表单提交事件,将新攻略动态插入到页面中,处理相关交互细节。</think>我将分步骤为您实现“添加攻略”功能,结合Bootstrap5模态框: $$html <!-- 添加攻略按钮(放在分类筛选区域) --> <button class="btn btn-primary btn-sm ms-3" data-bs-toggle="modal" data-bs-target="#addGuideModal"> <i class="fas fa-plus me-2"></i>添加攻略 </button> <!-- 模态框 --> <div class="modal fade" id="addGuideModal" tabindex="-1"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <!-- 模态框头部 --> <div class="modal-header"> <h5 class="modal-title">发布新攻略</h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <!-- 模态框表单 --> <form id="guideForm"> <div class="modal-body"> <!-- 标题输入 --> <div class="mb-3"> <label class="form-label">攻略标题</label> <input type="text" class="form-control" name="title" required> </div> <!-- 分类选择 --> <div class="mb-3"> <label class="form-label">分类</label> <select class="form-select" name="category" required> <option value="history">历史人文</option> <option value="nature">自然风光</option> <option value="food">美食之旅</option> </select> </div> <!-- 内容编辑 --> <div class="mb-3"> <label class="form-label">攻略内容</label> <textarea class="form-control" rows="5" name="content" required></textarea> </div> <!-- 片上传 --> <div class="mb-3"> <label class="form-label">封面片</label> <input type="file" class="form-control" accept="image/*" name="cover"> </div> </div> <!-- 模态框底部 --> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> <button type="submit" class="btn btn-primary">发布攻略</button> </div> </form> </div> </div> </div> ``` $$javascript // 添加表单提交处理 document.getElementById('guideForm').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); // 这里应添加AJAX请求到后端接口 console.log('提交数据:', Object.fromEntries(formData)); // 临时前端演示效果 const newGuide = { title: formData.get('title'), category: formData.get('category'), content: formData.get('content') }; // 清空表单 this.reset(); // 关闭模态框 bootstrap.Modal.getInstance(document.getElementById('addGuideModal')).hide(); // 显示成功提示 alert('攻略提交成功(演示效果,实际需要后端接口)'); }); ``` 实现要点说明: 1. **界面整合**: - 在现有导航栏添加$btn-primary$样式的触发按钮 - 使用$modal-lg$创建大尺寸模态框适配攻略内容 - 表单包含标题、分类选择器(与筛选分类一致)、富文本内容区和片上传 2. **功能特性**: - 必填字段验证(通过HTML5 required属性实现) - 片格式限制(accept="image/*") - 表单提交后自动重置+关闭模态框 - 响应式布局适配移动端 3. **扩展建议**: $$html <!-- 可添加的增强功能 --> <template id="guideTemplate"> <div class="col-md-4"> <div class="card h-100"> <img src="..." class="card-img-top" alt="..."> <div class="card-body"> <span class="badge bg-success"></span> <h5 class="card-title"></h5> <p class="card-text"></p> </div> </div> </div> </template> ``` 后续可结合AJAX将数据提交到后端,使用模板动态渲染新攻略卡片。需要后端配合实现数据存储和片上传功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值