Canvas 多端实现生成图片及保存功能

栏目: Html5 · 发布时间: 6年前

内容简介:在项目中需要实现生成图片并保存到本地的功能,其中包含网络图片及后端接口返回数据。 而本文开篇为

在项目中需要实现生成图片并保存到本地的功能,其中包含网络图片及后端接口返回数据。 而 canvas 作为 HTML5 中新增的标签,主要用于在网页实时生成图像,并且可以操作图像内容,故选取 canvas 画图方式进行实现是一个不错的选择,并且可以通过转化为图片格式,来实现图片的下载保存功能。

canvas的多端实现及对比

本文开篇为 canvas 多端实现的图文对比及基本使用方式,比较适合 canvas 入门。对于已经熟悉 canvas 的同学,也可以直接阅读后文关于 canvas 实现过程中遇到的一些问题,比如无法实现长按下载及 ios 中出现的图片被旋转的兼容性总结,希望能够对大家有所帮助~

Canvas 多端实现生成图片及保存功能

canvas在H5中的实现

项目架构采用vue.js单页面应用。主要实现过程是通过 <canvas> 进行绘图,并转换成 <img> 标签展示,以此实现长按下载功能。

  • 创建canvas标签

由于要对图片实现长按保存, canvas 标签无法直接实现,而后文将采用 img 标签进行覆盖以实现该功能。故此处将 canvas 样式设置为 display:none 进行隐藏。

  • getContext() 方法获得渲染上下文和它的绘画功能

注意此处创建 canvas 绘图上下文要在 mounted 函数中创建,即页面完成挂载之后执行,否则会报无法读取未定义属性 getContext 的错误。 getContext() 只有一个参数:上下文的格式,此处为 2D 图像。

  • 引入图像到 canvas

  • 通过  newImage() 获得一个指向  HTMLImageElement 的对象

  • img.setAttribute('crossOrigin','anonymous') 解决跨域问题

  • img.src 设置图片源地址

  • 使用  drawImage() 函数将图片绘制到  canvas 画布上

图片加载是异步的,若调用 drawImage() 时图片没加载完那画布上就会是空的,用 onload 事件保证不会在加载完毕之前使用这个图片。

  • 将 canvas 转换成图片格式

此时可以得到以 base64 编码的 base64Url ,参数 type 指定图片类型,如果指定的类型不被支持则以默认值 image/png 替代; encoderOptions 可以设置图片质量。

  • 实现保存图片到本地

将返回的 base64Url 赋值给 <img> 标签的 src 属性,即可将绘制完成的图像以 <img> 标签展示出来。

使用上述方式通常可以直接实现长按下载并保存至本地。但在安卓系统中,却可能存在app 中不支持直接长按保存以 base64 格式展示的图片的情况,故本文第二部分便针对该问题进行了实现。

canvas在小程序端的实现

canvas是小程序的原生组件,使用时需注意相关限制。其实现思路虽与H5中大致相同,但由于小程序封装了自身的api,故本文对其进行了相应分析与总结。基本实现方式如下:

  • 创建canvas标签,此处需指定canvas-id作为canvas 组件的唯一标识符

  • 创建 canvas 绘图上下文

使用 wx.createCanvasContext 方法创建 canvas 绘图上下文,返回 CanvasContext 是小程序内建的一个对象,包含了一些绘图的方法可供使用。

  • 引入图像及文字到 canvas

由于小程序本身不支持在手机端用 canvas 绘制在线图片,所以需要把图片的在线地址换成本地路径,然后再用本地路径去进行 canvas 绘制。

  • 使用  wx.getImageInfo() 获取图片信息,返回图片本地路径(即下载一个网络图片到本地,同时需先配置  download 域名才能生效)

  • 使用  drawImage() 方法绘制图像到画布

  • 必须使用  draw() 方法将绘图上下文中的描述绘制上去,否则页面将为空

  • 将canvas 转换成图片格式

wx.canvasToTempFilePath() 方法把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径。

  • 保存图片到系统相册

使用 wx.saveImageToPhotosAlbum() 保存图片到系统相册,需要用户授权 scope.writePhotosAlbum 。其中参数 filePath 是图片文件路径,可以是临时文件路径也可以是永久文件路径,注意不支持网络图片路径。

小结:无论是 H5 中的 toDataURL() 方法还是小程序中的 canvasToTempFilePath() 方法,都需要在图片加载完成后执行,否则页面将会呈现空白。由于我们无法精准得到图片完成加载的时长,故此处最好添加回调或使用 promise 对象,以确保后续处理任务(比如传递到其他服务器或保存相册)成功执行。

canvas 实现中遇到的问题

图片无法长按保存问题

在一般的开发中, canvas 标签虽没有像小程序这样可直接实现保存至相册的方法,但却可以通过转换成 <img> 标签进行展示,通过长按下载来保存至相册。但安卓手机在某些 app 中却存在不支持直接长按保存以 base64 格式展示的图片的情况。故针对这种情况本文将 base64 数据适当处理,并通过后端返回图片地址来实现长按保存图片至本地功能。

  • 由于后端上传接口又大多接收文件格式的数据,此处首先将  base64 格式转换成  blob 格式:

  • 然后添加至  FarmData 对象并传输后端,通过将返回的  url 数据赋值给  img 标签的  src 属性机箱展示,即可实现长按下载保存功能

ios拍摄的图片被旋转问题

当绘制的 canvas 图片中包含本地拍照上传的图片时,那么又会出现一个新的问题,如果使用本地拍照功能, ios 会针对横竖屏拍照进行处理, ios 竖屏拍照上传的照片,在安卓系统下显示会被旋转90度,故此时可以采用 canvas 对特定图片进行旋转解决方式。

  • 首先获取 ios 拍照信息

判断当前系统是否为 ios ,如果是的话此处可通过采用 exif-js 插件来读取图像的原始数据,以获取拍照方向。

  • 针对ios竖屏拍照,即拍摄方向属性  Orientation=6 时,可应用  canvas 的  rotate() 方法将其旋转90度,再后续对图片进行保存处理

总结

本文分别从 canvas 的多端实现及 canvas 使用过程中遇到的一些问题进行了总结,如果你还没有入门 canvas 的话,也许能从本文对 canvas 有个初步了解,并希望可以获得些许帮助。而 canvas 的深入使用还有很多地方值得探索,希望大家多多尝试并提出宝贵意见。当然,我们的公众号里有更多小哥哥小姐姐带来的前言技术文章,关注走起!~~


以上所述就是小编给大家介绍的《Canvas 多端实现生成图片及保存功能》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程人生

编程人生

Peter Seibel / 图灵俱乐部 / 人民邮电出版社 / 2011-1-1 / 79.00元

界顶尖的程序员是怎么走上编程道路的? 他们的编程工作创造和改变了人类历史,在这一过程中都有哪些经验和教训? 他们对计算机软件行业的过去、现在和未来有什么独到的看法和见解? 他们对培养、发现、选拔、面试优秀的程序员有什么建议? 放下手头的工作,听听这些软件先驱们的故事和建议,眼界可以更开阔,思路可以更清晰,方向可以更明确,人生可以更精彩。 作者Peter Seibel采......一起来看看 《编程人生》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试