项目中遇到了长按保存为图片的需求, 就是将微信 H5 页面生成图片并保存到本地, 记录下操作流程.

更新


[2019-12-11]

  • Initial release

解决


思路一


页面挂载完成之后, 结合 html2canvasDOM 绘制到 canvas 画布上面, 接着将 canvas 转为图片 base64 码即可.

1
2
<div id="domWrapper"></div>
<img src="" id="imagePreview" alt="" />
1
2
3
4
5
6
7
// 1. DOM -> canvas
html2canvas('#domWrapper', {}).then(($canvas) => {
// 2. canvas -> image
const imgURL = $canvas.toDataURL('image/jpeg');

'#imagePreview'.setAttribute('src', imgURL);
});

但是要注意的是, 要将图片固定至页面的最上方, 方便调用微信浏览器内置的保存弹窗, 昨天在这一点上思考了很久, 其实微信浏览器是有内置的保存图片到本地的功能的.

1
2
3
<section class="save-image">
<img src="" alt="" />
</section>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.save-image {
position: fixed;
left: 0;
top: 0;
z-index: 9999;
width: 100%;
height: 100%;
opacity: 0;
img {
display: block;
width: 100%;
height: 100%;
}
}

坑点


1. 文字设置了颜色渐变(background-image), 截图后整个容器都会有阴影:

1
2
3
<span class="main-center-fish-text">
duanzhaoyang
</span>
1
2
3
4
5
6
7
8
9
10
11
12
span.main-center-fish-text {
background-image: -webkit-gradient(
linear,
-11 21,
-12 bottom,
from(#202020),
to(rgba(249, 218, 162, 0))
);
color: transparent;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}

解决方案: 采用 mask 的方式来设置文字渐变效果, 本质上就是给元素设置了一个遮罩层:

1
2
3
4
5
6
7
8
span.main-center-fish-text {
color: #202020;
mask: linear-gradient(
to bottom,
#202020,
rgba(249, 218, 162, 0)
);
}

2. html2canvas 生成后的图片的元素很模糊

解决方案: 可能有多种因素导致:

  • 设计稿的图片本身就很模糊
  • 移动端的 dpi 远远小于冲洗照片所要求的最低限度, dpi 则是每英寸(1英寸 = 2.54厘米)所包含的像素点数量, 所以提高相应的 dpi 大小即可, 但是这样做会增大生成的图片的体积

参考: