最近接到的一个新需求:页面一个静态H5,中间有一页是输入信息,然后跳转到最后一页,自动将页面生成图片,用户可以长按图片保存到手机上。

展示一下最后一页的样子:

刚拿到这个需求,在网上看了很多文章,最普遍的是使用 html2canvas + canvas2image  来实现。于是,跟着前人的脚步,踏上了一个不断采坑采坑采坑的旅程。

下面直接描述我在做这个需求过程中遇到的问题以及解决办法吧:

1.html2canvas 图片跨域:

这个问题网上很多解决办法:

这个是最常用的, 刚开始我只是加了红色框里面的这一句,但是并没有任何作用,依旧报错。后来看到有人说,加上前面那一句,所以果断在加进去。

这两句其实表达的是同一个意思:允许图片跨域。

当然,也有网友说,直接给一个空值就可以,我当时试了一下,并不ok~~~~.

2.多次使用canvas drawImage 方法图片展示问题

2.1 图片加载顺序问题

在我这个需求里面,肯定是文字描述以及二维码是展示在图片上面的,刚开始我是

1. drawImage   文字,

2. drawImage    二维码

3. drawImage   背景大图

然而,结果让我大吃一惊,只有背景图加载渲染出来了。然后,通过无所不能的网络才知道:drawImage 的顺序应该是:图片最底下的需要最先加载渲染。

2.2 图片显示不完整

在2.1 问题出现的同时还遇到了这个问题,图片渲染不完整,这。。nima。。。需求才刚开始做,怎么这样为难一个小女子。。。

不过有问题嘛,就解决咯。

图片渲染不完整,原因就是:在图片还没有加载完成的时候,canvas 就开始进行渲染。

因此解决办法就是:等图片加载完成后再进行drawImage 操作就可以啦,上~~~~代码:

3.canvas 保存为图片的跨域问题

遇到这个问题,我真的是花了一堆一堆的时间来看文章,看博客,,。

这会万能的网友给我的解决办法并没有任何效果:

他们说:1.把图片取下来放在自己服务器上(我用的公司的图片服务器。但是和我的放代码服务器不是同一个地址啊)

2. 用canvas2Image 啊,然而,,这不也是跨域么,,并没有啥,,用。

3.还有啥来着,,忘了,反正那天搞得我精神崩溃,,,也没解决到问题,,后来实在忍不住,问了公司的大神:大神说:你用base64 的呢。。

一语惊喜梦中人,对啊,这种方法多棒,这样就不会跨域了啊。当时为了赶进度,直接在线吧图片转成basa64  ,然后存成一个js 文件。

当时是这样的:红框里表示的是文件的格式。。、

至此,我的html 已经转为canvas  并且从canvas 转为img 存在页面上了,,

后来我在看这一段,觉得似乎不太好,这个文件显得很大,所以我想在用这个文件的时候在把它转成base64 的格式,,

1.利用canvas todataUrl 将图片转为base64

但是这种方法不可避免的会出现跨域的问题,pass

2.base64.js

这个文件中中文转码会出问题,而且我试过了,基本的字符串转码都是ok 的,但是对于文件转码就会出问题

3.浏览器原生的并且都支持的一个东西: window.atob     and   window.btoa

window.atob  是将base64 格式转换为字符串或者二进制编码格式

window.btoa  是将字符串或者二进制编码 格式转换为base64  格式  所以上面的base64.js 真的,,别浪费时间精力去看了,,

那文件编码解码呢?

原生的也有方法:FileRender()  这个构造函数,

var reader = new FileReader();

reader.onload = function(e) {

// e.target.result

};

reader.readAsDataURL(file);

这种方法没有测试过o(╥﹏╥)o。。

所以,目前为止,需要把文件转为base64. 格式的,我并没有找到合适的方法或者js 插件来操作,如果各位有什么好的办法,麻烦告诉我(* ̄︶ ̄)。

4. 图片模糊并且窗口中只显示了一部分

才定义canvas 的时候,我是给canvas 定义了一个宽高的,宽高是背景图的大小,因此在drawImage 的时候是按照canvas 实际尺寸进行渲染。

但是转为图片的时候是按照窗口的尺寸来进行的,因此图片会模糊,如果给图片设置canvas 宽高的话,图片在窗口中又显示不完整。

因此,就需要计算设备的retio,

基本思路:计算出ratio  ---> 然后canvas 转 img (按照canvas 实际尺寸进行渲染) ---> 图片按照窗口大小进行缩放

这个方法直接返回的是设备的ratio..

然后我们在进行canvas 渲染的时候,

在后面进行图片渲染的时候,图片的宽度直接除以 ratio ,这样图片就能完整的显示在窗口中。

 

5. ios10.2 canvas 转图片 一片黑

至此,页面是呈现出来了,并且在我的安卓(华为)上测试是ok

但是需求的同学(ios)告诉我:她的手机上最后一页是黑色的和,顶部有个白色框,,,我一懵,天,不会ios 不支持吧。

于是,用了旁边座位同学的手机。恩,也不行。。

啊啊啊啊啊,要崩溃。

在网上看了一下,有一种解决办法就是:使用双缓冲(出现黑屏的可能就是在drawImage 的时候计算量很大,然后渲染卡顿不成功)

大概思路就是:在新建一个cachecanvas 刚开始其实是把图片渲染在这个缓存的canvas 中的,然后在将cachecanvas 中的内容渲染到需要在页面展示的canvas 中。

我在中间使用了一个延时,时间虽然很短,但是这样也能确保cachacanvas 确实渲染完成在进行正式的canvas 渲染。

这样,我周围座位上的ios 上最后一页都能显示出来了,,但是那个ios10.2 的依旧不行,,啊,网上查了一下,这个版本的问题一直存在,所以,(꒦_꒦) ,

就这样,这个需求在我不断采坑的过程中,好像也快完结了,这里很少直接贴代码进来,因为贴进来似乎看的不太好,所以我基本上是截图的。

最后,几个小tips :

1.直接将网页图片存成base64 格式的,如果图片很少,可以,如果图片很多,还是建议不要这么操作了,比较一个base64的数据格式就已经很大了。。。

2.图片先压缩,然后在进行base64格式编码吧

3.对于drawImage 的位置,是相对于canvas  实际尺寸的。所以如果使用百分比,建议先得到窗口的宽高,然后在进行赋值。

4. 在使用canvas   fillText 的时候,有一个限制最大宽度,就是fillText 的最后一个参数(直接写数值即可,不用带单位,默认似乎是px)。

5.对于一般的H5,还是对图片进行预加载一下吧,。。(网上很多图片预加载的方法,自行查找哦)。

H5 中html 页面存为图片并长按 保存的更多相关文章

  1. Android Base64图片无法长按保存 问题解决

    踩了一个巨坑. 目前微信ios/android 均能长按保存src=base64的图片  (微信android x5 专门解决了这个问题); 但是android其他App没有针对解决这个系统问题(姑且 ...

  2. jQ处理页面中尺寸过大的图片

    这是一个非常实用的功能,在网页里难免会出现一些尺寸过大的图片,会将页面撑开或者图片被部分隐藏,我们通常会用css的max-width来加以 控制,但ie6却不吃这套.我在做一个站时,就遇到这种困惑,因 ...

  3. 从web图片裁剪出发:了解H5中的canvas

    本篇内容不针对canvas文档对每个api进行逐个的详解! 本篇内容不针对canvas文档对每个api进行逐个的详解! 本篇内容不针对canvas文档对每个api进行逐个的详解! 重说三,好了,现在进 ...

  4. Hybrid App中原生页面 VS H5页面(分享)

    本文部分转自  http://www.jianshu.com/p/00ff5664e000 现有3类主流APP,分别为:Web App.Hybrid App(混合模式移动应用,Hybrid有“混合的” ...

  5. Hybrid App中原生页面 VS H5页面

    Hybrid App中原生页面 VS H5页面   现有3类主流APP,分别为:Web App.Hybrid App(混合模式移动应用,Hybrid有"混合的"意思). Nativ ...

  6. 使用JavaScript 中的Math对象和勾股定理公式,计算鼠标的位置与页面图片中心点的距离,根据距离对页面上的图片进行放大或缩小处理。距离远时图片放大,距离近时图片缩小

    查看本章节 查看作业目录 需求说明: 使用JavaScript 中的Math对象和勾股定理公式,计算鼠标的位置与页面图片中心点的距离,根据距离对页面上的图片进行放大或缩小处理.距离远时图片放大,距离近 ...

  7. 微信中通过页面(H5)直接打开本地app的解决方案

    简述 微信中通过页面直接打开app分为安卓版和IOS版,两个的实现方式是完全不同的. 安卓版实现:使用腾讯的应用宝,只要配置了“微下载”之后,打开链接腾讯会帮你判断本地是否已经安装了app,如果本地安 ...

  8. h5页面转图片长按保存

    5页面经常会遇到此类需求.将最后的结果页转换为图片长按保存.下面介绍一下实现此需求的过程 1,依赖安装 cnpm install html2canvas --save 2,依赖引入,使用 绑定 初始化 ...

  9. 用H5中的Canvas等技术制作海报

    在去年的时候也实现过合成海报的功能,不过当时时间仓促,实现的比较简单. 就一个旋转功能,图片也不能拖动放大,也不能裁剪. 去年的实现可以参考<移动图片操作--上传>和<移动图片操作- ...

随机推荐

  1. dubbo 面试题

      dubbo是什么 dubbo是一个分布式框架,远程服务调用的分布式框架,其核心部分包含:集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等 ...

  2. luoguP4868 Preprefix sum

    https://www.luogu.org/problemnew/show/P4868 线段树上加等差数列,基础区间修改单点查询 等差数列具有可加性,当在同一段区间内时,首项相加公差相加即可 #inc ...

  3. go 递归实现快排

    package main import ( "fmt" ) func main() { arr := []int{1,2,5,8,7,4,3,6,9,0,12,13,45,78,8 ...

  4. root@localhost

    root代表当前的用户 也就是说你使用root的帐号登录的localhost是系统的名字 没有设置系统名字的时候默认名称是localhost/ 代表你当前所处的目录位置 你当前在根目录下# 是用户提示 ...

  5. 【问题记录】Python运行报错:can only concatenate str (not "int") to str

    自己总是写程序时候用 + 拼接的时候忘记变量类型要一致,如下面 frame_num = "1" for i in range(1, frame_num + 1, 1): self. ...

  6. C++_友元1-友元类是什么

    友元函数:不是类的成员函数,但是能够访问类的私有数据成员. 之前有个矛盾就是规定非成员函数不能直接访问类的私有数据,但是这会儿却可以,但那只是针对常规非成员函数而言,特殊的非成员函数就可以访问类的私有 ...

  7. Angular 组件 mat-paginator 自定义详细用法

    Demo: https://stackblitz.com/edit/angular-5mgfxh?file=main.ts 官方文档: https://material.angular.io/comp ...

  8. 洛谷 P2577 [ZJOI2005]午餐

    这道题目比较难想. 题解: 算法:贪心+dp 容易想到贪心:吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 然后就是dp了: 首先,应该想到f[i][j][k]:前i个人,在1号窗口打饭 ...

  9. ActionHelper

    /// <summary> /// 方法帮助类 /// </summary> public class ActionHelper { /// <summary> / ...

  10. java中的线程(1):如何正确停止线程Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?

    转自 : http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html 1.Why is Th ...