项目需求
需要在2天之内搞定分享功能,包括分享链接以及分享图片,主要说分享图片遇到的坑😂
- 用户点击分享图片,生成一个全屏分享图
- 用户点击保存,图片保存到本地
无法保存到本地
巨坑1 -- 保存图片到本地,行不通
尝试说服产品经理砍掉这个需求
尝试了网上N多种方案,都不行,只好尝试最后一种方案
说服产品经理,砍掉这个需求
产品经理提出建议,人家都能做,你为什么不能?
- 查看产品经理给出的网址,分析源码,发现真相
- 人家根本就没做,只是长按能触发浏览器自带的保存图片功能
- 瞬间悟了,原来还能这么搞...
方案变种,生成图片,让用户长按图片进行保存
- 确定生成图片方案,调研
DOM生成图片的第三方仓库,快速完成需求 - 经过使用复杂度,以及项目
ISSUE对比, 决定使用dom-to-image 进行保存。
生成图片模糊
小坑1 -- 生成的图片有点模糊
**我拿着手机进行测试,这图片怎么这么模糊**推测可能的原因🤔️
- 是不是图片的质量没有开到最高?
- 是不是生成图片的格式问题?
- 生成图片的宽高比较小?
- 这个组件库不能生成高清图片?
经过一一测试跟比对,全部否决
那是啥问题?(此时表情已渐渐抓狂😫)解决方案
将图片缩放3倍,配置如下
const scale = 3;
const style = {
transform: 'scale(' + scale + ')',
transformOrigin: `10px 0`,
width: width + 'px',
height: height + 'px',
};
const param = {
height: height * scale,
width: width * scale,
quality: 1,
style,
};
dom-to-image 兼容性不太好
大坑2 -- `svg foreignObject` 兼容性不太好,部分浏览器生成不了图片
* 用`UC`浏览器进行测试,无问题 * 用`微信`浏览器进行测试,无问题 * 用`QQ`浏览器进行测试,`Error: XXX` * 报错了,用`IOS`手机再试试其它的浏览器,也提示 `Error: XXX`果然,事情不是那么顺利就能解决的
查看官方文档以及搜索ISSUE发现,项目中赫然写着不兼容Safari 以及 IE浏览器
当时自己为啥要选择使用这个仓库???🤔️
经过再次对比,决定使用 html2canvas 这个仓库,先让 html 生成 canvas 再生成图片
没问题了,嘿嘿😁
html2canvas 部分属性样式无法还原
小坑3 -- `html2canvas` 部分属性样式无法还原,图片生成有白边
* 这确实没办法了,要么不用不支持的样式,要么用其它方式实现类似的`css`效果 * 天生受限,绘制出的图片还原度不是很高,**暂时解决不了**图片生成有白边,排查了下,是因为滚动造成定位不准造成的
产品坚持想要border-image的效果,只好用其它支持的样式来模拟了
- 叠一个
div用background: linear-gradient()属性模拟border-image
还原度不太好的问题,还是无法解决,无奈只有采用这种方案
- 使用
dom-to-image支持大部分浏览器,html2canvas生成的图片只能将就将就了,毕竟时间催得紧
经过一顿操作之后,终于没问题了,测试接手,上线到预发环境
图片请求缓存,跨域
巨坑2 -- 生成出来的图片里面,有些图片元素没有绘制出来
* 打开控制台,发现请求图片,有跨域报错 * 瞬间定位问题,发现线上走的静态资源的地址是不同域名,而测试环境用的是一个域名,所以可能会有跨域的问题🤔 * 自信的打开控制台, 查看`Response Headers`, 发现允许跨域的请求头没有返回 * 马上找到运维同学,询问为何没配置,跨域相关的请求头,然后被打脸了...我:为啥这个域名的跨域请求头没配置?
运维:不可能,我配置了,咋个没有嘛!
我:你看看,没有返回啊,你确定配置了吗?
运维:你用 curl https://xxxx 试一下,看看返回没有嘛
我:我还不信了,马上试试... 真的返回了,卧槽😂
那这个到底是咋回事!!!(表情已经狰狞了😫)
强迫自己沉着冷静的思考了一番
运维配置了跨域允许,但是请求没有返回,然后预览图还可以出来。
只是生成截图的时候,图片跨域了,然后... 一团乱麻
因为必须要上线,短短的时间之内,心态还是没稳住,冷静不下来
求助一下其他小伙伴吧
求助了几个小伙伴,得到的答案都类似
小伙伴1. 这个我做过类似的,我们那个域名没问题。
小伙伴2. 是缓存的问题吗?(🐂🍺)
查看小伙伴1他们的域名,发现配置的头是 Access-Control-Allow-Origin: *
然后让运维尝试一下,顺利解决该问题😊
过了两天之后,运维:这个配置可能有安全问题,有没有其它解决方案?
- 先是询问了运维,为啥没正常返回这个
Access-Control-Allow-Origin: https://xxx响应头 - 运维给出了一个答案:‘我也不太清楚,咱们用的
AWS的服务,是统一配置的CDN缓存策略以及响应头,我配了,只是你走的是缓存,所以没有。’ - 运维:我勾选了
Disable cache,就可以正常生成,就是浏览器的缓存问题,你们想办法解决!
行吧,目前的配置策略下,好歹知道了是因为缓存引发的问题
经过不断的尝试,查看第三方组件源码,摸索(询问其它小伙伴)的方式,终于确定了问题的原因
- 图片自身的请求,不会涉及到跨域问题,所以预览图能正常呈现
- 第三方组件生成图片时,会使用
xhr请求图片的地址,由于跨域配置没有返回以及配置的缓存策略,让这一次xhr的请求,走的是缓存逻辑,之前的请求没有返回响应头,所以这一次也没有
dom-to-image 有一个选项 cacheBust
- 开启这个选项之后,请求图片的时,会增加一个时间戳,让这次的请求不走缓存逻辑
html2canvas 没有提供类似的功能,只能改动源代码了...
加上随机数请求
小坑4 -- `Base64`加上随机数报错
干,没想到还有这一茬,改动源码,写上正则匹配,只增加http:// | https:// 开头的请求
终于解决了问题...
尾记
又过了两天之后,运维:解决了,配置有问题,你看看跨域头能返回了吗? 🐂🍺