h5如何实现下载图片(网页截图+下载图片到手机相册)
前言
最近在做的项目(移动端h5),产品有个这样的需求(参考淘宝的):
点击下载按钮,保存一个卡片式的图片到手机上
点击保存照片:
保存到手机相册的照片:
好了,需求都清楚了,那就开始实现吧~
实现
先梳理下实现思路,既然想保存一个卡片式的图片到手机上,那么我们就要先有这个卡片式的页面。再通过网页截图的方式生成图片。最后再进行下载到手机上。
好了,那么我们只需要做到以下两步即可:
- 网页截图生成卡片式图片
- 下载这张图片
网页截图生成图片
采用html2canvas + canvas.toBlob来实现。
1、安装
npm i html2canvas --save
2、创建卡片组件
card.vue
<template>
<div class="card">
// 在此写自己的卡片样式
</card>
</template>
3、图片生成+下载
在页面中引用
<template>
<div class="detail">
<span @click="saveImg">下载</span>
<!-- 展示需要下载的html -->
<div id="saveHtml">
<card />
</div>
</card>
</template>
<script>
import card from "./card.vue";
import { convertToImage, saveBlob } from "@/utils/convertToImage";
export default {
components: { card },
methods: {
async saveImg() {
let element = document.getElementById("saveHtml");
// 调用函数,取到截图的blob数据,对图片进行处理(保存本地、展示等)
const blob = await convertToImage(element);
// 下载图片到手机
saveBlob(blob, "访客凭证");
},
}
}
</script>
需求是点击下载,就保存卡片式的图片到手机上。
要想实现这点,我们就需要将我们的card卡片隐藏,视觉内看不到。
// 下载图片
#saveHtml {
position: absolute;
top: 0;
height: 570px;
z-index: -10;
}
使用html2canvas进行截图
import html2canvas from "html2canvas";
// 生成快照
export const convertToImage = (container, options = {}) => {
// 设置放大倍数
const scale = window.devicePixelRatio;
// 传入节点原始宽高
const _width = container.offsetWidth;
const _height = container.offsetHeight;
let { width, height } = options;
width = width || _width;
height = height || _height;
// html2canvas配置项
const ops = {
scale,
width,
height,
useCORS: true,
allowTaint: false,
...options
};
return html2canvas(container, ops).then(canvas => {
// 返回图片的blob数据
return new Promise(function(resolve) {
canvas.toBlob(function(blob) {
resolve(blob)
})
})
});
}
有个点需要解释下:
1、为什么使用canvas.toBlob来生成图片,而不是用canvas.toDataURL来生成呢?
答:使用canvas.toDataURL生成base64格式的图片,无法在移动端下载,PC端Chrome可以(其他类型浏览器未测试)。
下载图片
// 下载图像
export const saveBlob = (blob, fileName) => {
const a = document.createElement('a');
a.style.display = 'none';
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
}
获取到截图的blob数据后,使用URL.createObjectURL()
将blob数据生成一个图片url,最后使用a标签的download属性下载图片。
到此,其实就已经实现了图片生成和下载。
4、优化
在安卓机和苹果机上都进行了测试。
测试结果:在安卓机上可以下载图片,但在苹果机上无法下载到手机中。
优化思路:
- 安卓机上还是直接调用a标签下载图片
- 苹果机上使用弹框预览图片,让用户长按图片使用手机自带的保存图片功能保存图片到手机上。
在页面中添加一个预览弹框
<van-dialog
v-model="isIPhone"
:showConfirmButton="false"
:closeOnClickOverlay="true"
>
<img :src="img" />
<p class="textCenter">“长按”保存照片到手机</p>
</van-dialog>
获取到blob数据后,分步处理
// 判断是否ios
// 在ios移动端上直接预览图片,长按图片保存(ios系统不支持直接下载)
if (browser.versions.mobile && browser.versions.ios) {
this.img = window.URL.createObjectURL(blob);
this.isIPhone = true;
} else {
// 安卓机和网页端都直接下载到手机相册中
saveBlob(blob, "访客凭证");
}
经过安卓和苹果机的实测,效果不错。
补充
项目上线后,内嵌到安卓APP内,下载失效,经排查发现,如果安卓APP不支持下载图片,h5页面中下载会失效。有两种方案,一:安卓APP那边开发一个下载图片功能;二、舍弃下载功能,只支持预览图片
有小伙伴想看下完整代码,目前已经整理好,发到git上了,有需要的小伙伴可以去看看。地址
小记
时刻记录着,因为代码值得~
转载自:https://juejin.cn/post/7234782462773739578