引言

年后一直处于秣马厉兵的状态,上周接到了一个紧急需求,为38妇女节做一个活动页,主要功能是生成海报,第一次做这种需求,我也是个半桶水前端,这里将碰到的问题、踩的坑,如何解决的分享给大家,讲的不到位的地方还望斧正。

效果展示

目前活动还是在线状态,这里是最后生成海报的效果,扫描二维码就可以进入页面。

实现方案

起初实现的方案是展示的时候直接使用canvas,计算手机屏幕大小,让canvas充满整个屏幕,用户编辑完之后直接用展示的canvas生成图片,最后发现这种形式很麻烦,碰到适配问题,canvas计算起来比较麻烦。

最终方案,展示的时候使用html、css,这样用户看到的展示、编辑页面适配起来容易。最后生成图片的时候使用canvas,这个canvas是隐藏的,用户不可见,这样还有一个优点,最终生成的海报大小是固定的,跟手机屏幕大小无关。

方案看着很简单,实现的时候各种细节问题。

资源预加载

H5海报活动,就像一个小型的APP,体验一定要好,最主要的就是资源预加载了,整个应用大小有30个图片,还有字体文件,一个字体文件就有3MB多,如何做好资源预加载很大程度上影响了这次活动的体验。

图片预加载

图片预加载的原理就是使用http协议中的缓存,这里主要指的是强缓存(协商缓存还要去服务器,有网络交互)。在活动首页之前加个loading页面,将所有用到的图片加载一遍,等到后面加载的时候就只有几ms。

图片预加载,使用let image = new Image()创建一个图片标签,在image.src中加入图片链接,加载成功调用image.onload事件。一张图片还好,大量图片的话如何优雅的做出进度条呢?

还好有Promise这个银弹,我们可以轻松的实现进度条效果。

class Preloadedr {
/**
*
* @param images array 要加载的图片,数组
* @param processCb function 回调函数,加载中进度有变化就调用
* @param completeCb function 回调函数,加载完成调用
*/
constructor(images, processCb, completeCb) {
this.imagesElement = []
this.loaded = 0
this.images = images
this.total = images.length
this.processCb = processCb
this.completeCb = completeCb
} /**
* 开始预加载缓存图片
*
* @returns {Promise<any[]>} Promise 包含所有图片的promise
*/
preloadImage() {
let me = this
let promises = []
me.loadedAction()
me.images.forEach((img) => {
let p = new Promise((resolve, reject) => {
let image = new Image()
image.src = img
this.imagesElement.push(image)
image.onload = () => {
me.loadedAction(img)
resolve(image)
}
image.onerror = () => {
resolve("error")
}
})
promises.push(p)
}) return Promise.all(promises)
} /**
* 进度变化的时候回调,private
*
* @param key string 加载成功的图片地址
*/
loadedAction(key) {
if (key) {
this.loaded++
}
this.processCb(this.total, this.loaded)
if (this.total == this.loaded) {
this.completeCb()
}
}
}

每个要加载的图片都是一个Promise,将所有图片Promise包装为一个大的Promise,当这个大的Promise状态为fulfilled的时候,表明图片加载完成。要注意,包装图片Promise的时候onerror也是返回成功,这是因为Promise.all会包装出一个新Promise,这个Promise只要出现一个失败,就直接返回报错了,所以失败了也返回成功(resolve),就算有少数图片未加载成功也影响不大。

用起来也很简单:

(async () => {
let imgLoader = new Preloadedr([
"//avatar-static.segmentfault.com/606/114/606114310-5c10a92c87f07_huge256",
"//image-static.segmentfault.com/203/994/2039943300-5c515b79c91f1_articlex",
], (total, loaded) => {
console.log("process: 图片" + Math.floor(100 * loaded / total) + "%")
}, () => {
console.log("complete: 图片" + 100 + "%")
})
await imgLoader.preloadImage()
console.log("加载完成")
})()

可以看到输出如下:

process: 图片0%
Promise {<pending>}
process: 图片50%
process: 图片100%
complete: 图片100%
加载完成

至此,图片预加载就实现了。接下来我们看看字体的预加载,字体也是一种http静态资源,也可以使用缓存,但在实现预加载上却远没有图片这么简单。

字体预加载

字体预加载,没有像Image那么方便的函数回调使用,查了下资料,有个document.fonts实验性的属性,试了下基本支持,但在ios上可能会出现一点儿小问题,加载过一次有缓存了,第二次加载时候onloadingdone事件可能不会触发,另外这个属性、事件还是一个实验性的属性,浏览器支持程度未知,可能很差。

查了很多资料,无意中看到有人说webfontloader这个项目通过一种比较trick的方法实现了,原理就是下面这两句话:

不同字体,在将 fontSize 设置到很大的时候(比如300px),同一段文字,他展示的宽度是不一样的。

给两个div,同样的文字内容,第一段设置两种字体,待加载字体首选,默认字体备选,第二种只设置默认字体,定时器去扫描,当两段文字长度不同的时候就说明新字体加载成功可使用。

大概看了下webfontloader,代码写的比较凌乱,命名奇怪,注释少、没翻译(

H5海报制作实践的更多相关文章

  1. 【干货】微信场景之H5页面制作免费工具大集合

    营销代有手段出,各领风骚数百天.要说现在哪些营销方式最能传播,屡屡刷爆朋友圈的H5页面肯定就是首当其冲的,提到H5页面,就立马想到"围住神经猫",上线微信朋友圈3天的时间便创造了用 ...

  2. 易企秀 we+ Maka 兔展 四大H5页面制作工具

    H5这个由HTML5简化而来的词汇,正通过微信广泛传播.H5是集文字.图片.音乐.视频.链接等多种形式的展示页面,丰富的控件.灵活的动画特效.强大的交互应用和数据分析,高速低价的实现信息传播,非常适合 ...

  3. 【转】视频H5 video最佳实践

    原文地址:https://github.com/gnipbao/iblog/issues/11 随着 4G 的普遍以及 WiFi 的广泛使用,手机上的网速已经足够稳定和高速,以视频为主的 HTML5 ...

  4. 解决移动端H5海报滑动插件适应大部分手机问题 手机端高度自适应

    Html5微信端滑屏海报在各种尺寸的手机上总会有这样那样的问题,经过多次制作总结出来一些小心得,分享下. 我使用的是jquery插件swiper.min.js,动画可以利用animate.css,如果 ...

  5. h5快速制作工具-企业级. 非个人无水印

    Epub360 Epub是团队引入的专业级H5应用开发工具,能够快速制作出高质量的H5运营交互页面,具有动画控制.交互设定.社交应用和数据应用的特点,其制作过程就类似于制作一个PPT,比较容易上手. ...

  6. [转]15年双11手淘前端技术巡演 - H5性能最佳实践

    [原文地址]:https://github.com/amfe/article/issues/21 前言 2015年是全面『无线化』的一年,在BAT(财报)几家公司都已经超过50%的流量来自移动端,这次 ...

  7. weex h5开发区别-实践初级篇

    html标签 weex中没有标签的概念,html中标签对应于weex中的Components weex 无<span> .<p> ,用<text>替代.但是< ...

  8. C# Note19: Windows安装包制作实践

    前言 最近在项目中需要不断更新新版本的software installer(软件安装包),于是便查阅资料,整理了下制作方法. NSIS安装包制作脚本 NSIS(Nullsoft Scriptable ...

  9. UI设计教程分享:PS故障风海报制作教程

    1.首先找一张看起来很酷的图(也可以选择自己喜欢的图片):   2. 复制图层,点击添加图层样式,选择混合选项,在高级混合里面的通道选项,有R.G.B三个通道选项,默认是全部勾选的状态,选择其中一个勾 ...

随机推荐

  1. (后端)springboot 在idea中实现热部署(转)

    自己用到了iIntelliJ IDEA 这个ide工具,但是和以前的工具写html,css,js直接刷新页面不同,这个需要去热部署,网上搜的解决方法: SpringBoot的web项目,在每一次修改了 ...

  2. (网页)HTML中INPUT type="date"标签如何赋值注意问题(转)

    现在的html5 input标签支持type="date" 显示有日期的日历控件,一行简单的代码就能显示出一个日历控件,但是有的时候需要给它一个默认的日期值,这个时候可能就要用到v ...

  3. 翻译:MySQL "Got an Error Reading Communication Packet" Errors

    前言: 本文是对Muhammad Irfan的这篇博客MySQL "Got an Error Reading Communication Packet" Errors的翻译,如有翻 ...

  4. ArcGIS Server服务器监控

    最近项目上需要对服务器与ArcGISServer服务进行监控,做了一个初步的原型,实现了以下功能. 一.服务器监控 注册服务器 服务器运行状态监控 在线状态 CPU.内存.存储配置监控,由于现在很多采 ...

  5. 简单易懂的程序语言入门小册子(1.5):基于文本替换的解释器,递归定义与lambda演算的一些额外说明

    这一篇接在第一篇lambda演算的后面.讲讲一些数学知识. 经常有些看似很容易理解的东西,一旦要描述得准确无误,就会变得极为麻烦. 软件工程里也有类似情况:20%的代码实现了核心功能,剩下80%的代码 ...

  6. Python常用的数据类型转换

    在实际开发中.经常要根据需求来转变一些变量的类型. 需要用到以下函数:

  7. Jenkins系统监测

    Jenkins 是一个开源项目,提供了一种易于使用的持续集成系统,使开发者从繁杂的集成中解脱出来,专注于更为重要的业务逻辑实现上.同时 Jenkins 能实施监控集成中存在的错误,提供详细的日志文件和 ...

  8. AI学习---特征工程【特征抽取、特征预处理、特征降维】

    学习框架 特征工程(Feature Engineering) 数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已 什么是特征工程: 帮助我们使得算法性能更好发挥性能而已 sklearn主 ...

  9. LeetCode算法题-First Bad Version(Java实现-三种解法)

    这是悦乐书的第200次更新,第210篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第66题(顺位题号是278).您是产品经理,目前领导团队开发新产品.不幸的是,您产品的最 ...

  10. JavaScript数组对象详情

    Array 数组概述 Array 类型是 ECMAScript 最常用的类型.javaScript 中的 Array 类型和其他语言中的数组有着很大的区别. 虽然数组都是有序排列,但 javaScri ...