资讯专栏INFORMATION COLUMN

H5海报制作实践

苏丹 / 2811人阅读

摘要:效果展示目前活动还是在线状态,这里是最后生成海报的效果,扫描二维码就可以进入页面。最后生成图片的时候使用,这个是隐藏的,用户不可见,这样还有一个优点,最终生成的海报大小是固定的,跟手机屏幕大小无关。方案看着很简单,实现的时候各种细节问题。

引言

年后一直处于秣马厉兵的状态,上周接到了一个紧急需求,为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} 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 {}
process: 图片50%
process: 图片100%
complete: 图片100%
加载完成

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

字体预加载

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

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

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

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108996.html

相关文章

  • fastposter 2.4.0 全新发布 低代码海报生成器

    摘要:支持等多种语言。全新发布低代码海报生成器生成二维码 fastposter 2.4.0 全新发布 低代码海报生成器fastposter低代码海报生成器,一分钟完成海报开发。支持​​Java​​、​​Python​​、​​PHP​​、 ​​Go​​、​​JavaScript​​等多种语言。v2.4.0 全新发布 电商级海报生成...

    番茄西红柿 评论0 收藏2637
  • Golang Gin实践 连载十五 生成二维码、合并海报

    摘要:实践连载十五生成二维码合并海报原文地址实践连载十五生成二维码合并海报项目地址如果对你有所帮助,欢迎点个 Golang Gin实践 连载十五 生成二维码、合并海报 原文地址:Golang Gin实践 连载十五 生成二维码、合并海报项目地址:https://github.com/EDDYCJY/go... 如果对你有所帮助,欢迎点个 Star

    twohappy 评论0 收藏0
  • 如何优雅的生成海报/动态合成图片 ?

    摘要:感谢提供的图床服务适用场景我希望这个项目用于渲染需要动态合成的图片,例如用户名片需要动态渲染名字和头像等,而非一经渲染就恒定不变的,例如等。快速找到适合自己的海报,快速集成可扩展高性能的海报渲染功能。 poster-generater ⚡⚡⚡海报生成器. 只需要一个简单的 json 配置即可生成你需要的海报... 说明 此项目诞生有一段时间了,我本人也一直在使用这个程序,从一开始的 g...

    hearaway 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<