likes
comments
collection
share

h5如何实现下载图片(网页截图+下载图片到手机相册)

作者站长头像
站长
· 阅读数 56

前言

最近在做的项目(移动端h5),产品有个这样的需求(参考淘宝的):

点击下载按钮,保存一个卡片式的图片到手机上

点击保存照片:

h5如何实现下载图片(网页截图+下载图片到手机相册)

保存到手机相册的照片:

h5如何实现下载图片(网页截图+下载图片到手机相册)

好了,需求都清楚了,那就开始实现吧~

实现

先梳理下实现思路,既然想保存一个卡片式的图片到手机上,那么我们就要先有这个卡片式的页面。再通过网页截图的方式生成图片。最后再进行下载到手机上。

好了,那么我们只需要做到以下两步即可:

  1. 网页截图生成卡片式图片
  2. 下载这张图片

网页截图生成图片

采用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、优化

在安卓机和苹果机上都进行了测试。

测试结果:在安卓机上可以下载图片,但在苹果机上无法下载到手机中。

优化思路:

  1. 安卓机上还是直接调用a标签下载图片
  2. 苹果机上使用弹框预览图片,让用户长按图片使用手机自带的保存图片功能保存图片到手机上。

在页面中添加一个预览弹框

<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
评论
请登录