这一篇要说说裁剪、压缩,这两个功能都要用到 canvas 的能力,canvas 在 IE9 以上浏览器都支持良好,也为 IE9 提供为数不多的可以进行文件操作的 API。
基础代码
<div id='box'></div>
const canvas = document.getElementById('box')
const ctx = canvas.getContext('2d')
如何给 canvas 导入图片
通过实例方法 drawImage
可以在canvas 中绘制图片。
drawImage
接受的第一个参数描述如下:
An element to draw into the context. The specification permits any canvas image source (CanvasImageSource), such as an HTMLImageElement, an HTMLVideoElement, an HTMLCanvasElement or an ImageBitmap.
但是 IE9 中无法传入一个加载了图片的 IMG 元素。
换种思路,在 IE9 中做以下兼容处理:
先把图片上传,然后加载远程图片进行处理,但是碰到一些问题:
- 如果本地图片过大,上传并下载耗时严重
- canvas 由于安全问题无法加载跨域图片,导致上传 CDN 的方案无法使用
或者直接上到 CDN (我们用的是七牛),并把上传后的 key 以及裁剪参数传给后台,通过后台调用七牛的裁剪服务和持久化服务,但是问题又来了:
- 增加了后台服务的依赖,增加了请求数
- 由于七牛在持久化时,需要排队处理,不保证能实时预览
- 定时去轮询新的图片地址,经常需要耗时很长,并且有可能生成失败
- 即使通过临时展示剪裁服务返回回来的地址,也经常会出现持久化服务调用失败的问题,失败原因信息很少,调试很麻烦。
总的来说,这些方案性价比不高!
如何做裁剪
两种思路:
- 通过 CSS + JS 模拟可以获取 裁剪长宽 以及 裁剪起始位置,然后将参数输出给 canvas
- 直接在 canvas 里面操作
最后,都通过实例方法 drawImage
来进行裁剪。
如何压缩
github上有一个国人用 javascript 写的无依赖的本地压缩库 localResizeIMG3。
也可以继续用 canvas 的实例方法 toDataURL
简单实现
打脸的事情要开始了
利用 flash 制作了一个swf 文件,在 IE9 中选择图片、读取图片,并输出 base64 格式。
本来想把本地图片地址传给 swf 文件,让它直接读路径,但是由于安全问题,会被阻止,所以还得通过 flash 来选择图片
虽然被打脸,说几个好处:
- 可以统一加载 base64 格式的图片,图片预览,获取图片长宽,都不用单独处理 IE9
- 如果需要,可以扩展一个读取图片大小的功能
- 上传图片,可以直接用 xmlhttprequest 上传 Base64 格式的图片(这里用到的七牛 CDN 提供的上传 Base64 图片服务),不用后台配合搞 iframe 上传方案,或者加载第三方上传插件,通过 flash 上传
实现代码参考:https://github.com/yannickcr/...
现实是残酷的,七牛 CDN 上确实能找到一个古老的上传 base64 格式图片的服务,但是由于服务是跨域的,并且要求在请求头里面携带参数,因此 IE9 中是无法通过 Javascript 实现上传。
总结
- 如果支持 IE9 及以下浏览器,建议本地模拟裁剪,把裁剪参数和原图传给后台,剩下的都交给后台处理
- 如果支持 IE10 等高级浏览器,建议使用本地方案,把裁剪压缩后的图片传到 CDN。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。