1.最近在做移动端开发,框架是vue,一产品需求是,后台返回数据,通过qrcode.js(代码比较简单,百度上已经很多了)生成二维码,然后通过html2canvas,将html元素转化为canvas,通过 canvas.toDataURL() 方法转化为base64,二进制流的图片,显示在页面上,因为微信内置浏览器不支持下载(可能是我不会,谁实现了可以教一下我),需要用户触屏手动保存图片。下面贴出部分代码

 
2.
<template>
<section id="section">
  <p>当前积分<span>365</span></p>
  <p>参与项目数量<span>12</span></p>
  <p>募捐金额<span>45678</span>元</p>
  <p>荣誉等级<span>海绵宝宝</span></p>
  <div id="qrcode">
  </div>
</section>
<div id='photo'>
  <span>长按图片保存和分享</span>
</div>
 <button @click="saveImg">生成图片</button>
</template>
<script>
  export default{
    methods:{ 
      saveImg(){
        var shareContent = document.getElementById("section");
        html2canvas( shareContent,{
          onrendered: function(canvas){
          var img = new Image();
          img.src = canvas.toDataURL() ;
          document.getElementById("photo").appendChild(img);
          
        }
      })
    }
}
</script>
3.当然前提是先引入html2canvas文件,我直接在index.html 引入CDN 地址是

  

<script src="https://cdn.bootcss.com/html2canvas/0.4.1/html2canvas.js"></script>
不要问我为什么不用最新 0.5.0版本,网上有人说坑比较多,我项目赶进度,没来得及去踩坑,你们想尝试也可以玩玩。
 
4.然而,通过上述代码,PC端,包括开发者工具均可显示生成的图片,移动端安卓系统也能正常显示和保存。然而,坑坑的IOS图片区域一片空白;于是,本人开始漫长的百度之旅
 
5.说法1:ios显示base64图片,需要去除格式前缀
 我们通过控制台,可以看到canvas.toDataURL() 出来的格式,img src 可以直接显示 "data:image/png;base64,iVBORw0KGgoAAAANSU.....==="格式的图片,但是ios需要去除 data:image/png;base64 前缀,于是我通过以下判定,当是IOS系统时,去除前缀
   

 var u = navigator.userAgent, app = navigator.appVersion;
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //g
    var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
    if (isAndroid) {
      //这个是安卓操作系统
      mg.src = canvas.toDataURL() ;
    }
    if (isIOS) {
      //这个是ios操作系统
      mg.src = canvas.toDataURL() .replace("data:image/png;base64,","");
    }

然而开发者工具调为IOS手机,也出现系统报错,可以发现,去除前缀,浏览器会自动添加地址前缀。所以,这种解决办法失败。接着来

 
 
6.说法2,首先在页面添加img,通过给src赋值,完成,而不是appendChild
  

 

<div id='photo'>
  <span>长按图片保存和分享</span>
  <img src="" id="img">
</div>
  ..
  
  html2canvas( shareContent,{
    onrendered: function(canvas){
      document.getElementById("img").src = canvas.toDataURL() ;
    }
  }
  当然,结果依旧是空白一片 
 
7.说法3,无效

   

document.getElementById("img").src = canvas.toDataURL() .replace("image/png", "image/octet-stream") ;
 
8.说法4,blob格式生成http URL地址格式显示
 和说法1有点相关,当去掉IMG格式前缀,SRC会添加域名,显示地址,那我们直接显示地址行不行,有人通过后台完成,但是,太过复杂。尝试blob格式生成http URL?
  

function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','),mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
      u8arr[n] = bstr.charCodeAt(n);
    }
     return new Blob([u8arr], {type:mime});
   }
  let dataUrl = dataURLtoBlob(canvas.toDataURL()) ;
 document.getElementById("img").src = URL.createObjectURL(dataUrl);
 这样,IMG的SRC显示就不是base64格式,而是http格式的URL,但是,ios依然无法显示图片

8.做到这里,我产生了让后端帮助的念头,但随后放弃了,于是开始整理思路,我一直觉得是ios不支持base64格式图片,网上也有人说是ios11无法显示html2canvas.然而通过第四种借助http url的方法,还是没有成功,于是我开始思考是不是其他地方出现的问题。搜索了很多文章,忽然一个说法让我觉得很有可能是解决办法,那就是,ios系统无法动态给img src赋值,可以通过div 显示背景的方式显示图片。但是,即使可以成功,也完不成我这个项目功能,因为作为背景图的话,用户无法触屏保存图片...而,这里,就体现了框架相对原生JS的好处,我可以通过v-bind绑定src 再给data赋值的方式。激动的我赶紧尝试。
<template>
<section id="section">
  <p>当前积分<span>365</span></p>
  <p>参与项目数量<span>12</span></p>
  <p>募捐金额<span>45678</span>元</p>
  <p>荣誉等级<span>海绵宝宝</span></p>
  <div id="qrcode">
  </div>
</section>
<div id='photo'>
  <span>长按图片保存和分享</span>
  <img :src="url">
</div>
 <button @click="saveImg">生成图片</button>
</template>
<script>
  export default{
    data(){
      return{
        url:""
      }
    },    
    methods:{ 
      saveImg(){
        var shareContent = document.getElementById("section");
        html2canvas( shareContent,{
          onrendered: function(canvas){
          this.url = canvas.toDataURL() ;        
        }
      })
    }
}
</script>
 
大功告成!嗯...最后的原因只是因为ios不支持直接给img src赋值,
当然,还可以优化,比如加入截屏声音。
 

 //添加快门声音
  var audio = document.createElement("audio");
  audio.src = "/static/1374.wav";
  audio.autoplay = "autoplay" ;
  photo.appendChild(audio);
  setTimeout(()=>{
    photo.removeChild(audio);
  },2000);
 

html2canvas截屏在H5微信移动端踩坑,ios和安卓均可显示的更多相关文章

  1. 微信小程序踩坑集合

    1:官方工具:https://mp.weixin.qq.com/debug/w ... tml?t=1476434678461 2:简易教程:https://mp.weixin.qq.com/debu ...

  2. vue中使用html2canvas及解决html2canvas截屏图片模糊问题

    最近在项目中用到了html2canvas插件,遇到的一些坑写下来,与大家共勉. html2canvas  官方网站http://html2canvas.hertzen.com/index.html 这 ...

  3. Egret 生成 自带EUI 的微信小游戏 踩坑!

    1. 首先,再次被网上一大堆屎一样的资料搞得浪费了我一天时间.各种坑. 2. 本文先讲一种正确的方式,然后再列举坑. 去www.egret.com下载最新的引擎,我的最新版本是5.2.2. 然后就会被 ...

  4. html2canvas截屏用法

    <!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...

  5. java使用代理 html2canvas 截屏 将页面内容生成图片

    1.html2canvas 生成图片简单又好用,但涉及到跨域就会出现问题,官方给出的解决办法是设置代理.基本原理就是在后端将图片的数据生成base64再返回给前端使用.使canvas画布分析元素的时候 ...

  6. html2canvas 截屏 兼容手机端

    <template> <div> <!--<input type="button" id="btnsavaImg" valu ...

  7. 移动端踩坑之旅-ios下fixed、软键盘相关问题总结

    最近一个项目掉进了移动端的大坑,包括ios下fixed布局,h5唤起键盘等问题,作为一个B端程序员,弱项就是浏览器的兼容性和移动端的适配(毕竟我们可以要求使用chrome),还好这次让我学习了一下相关 ...

  8. 微信小程序踩坑之获取手机号

    最近在开发小程序遇到这样一个问题, 在用户点击授权后去解密手机号时会出现第一次失败,第二次成功的情况.研究了一段时间,终于找到比较合理的解决方案,在此记录并总结一下,希望可以帮助到大家. 需求描述 在 ...

  9. 微信小程序踩坑

    微信小程序自定义属性data-xx使用注意事项 data-xx采用驼峰式命名时,数据传递打印显示(以jxsName与jxsname打印显示对比) data-xx全小写命名时,数据传递打印显示

随机推荐

  1. [Python] Python 学习 - 可视化数据操作(一)

    Python 学习 - 可视化数据操作(一) GitHub:https://github.com/liqingwen2015/my_data_view 目录 折线图 散点图 随机漫步 骰子点数概率 文 ...

  2. C# 如何在Excel表格中插入、编辑和删除批注

    概述 为文档添加必要的批注可以给文档使用者提供重要的提示信息,下面的示例中,将介绍通过C#编程语言来给Excel表格中的指定单元格内容添加批注,此外,对于已有的批注,如果需要修改,我们也可以进行编辑或 ...

  3. 让Mongo在Spring中跑起来

    本文标题为<让Mongo在Spring中跑起来>,旨在Spring中如何成功连接MongoDB并对其进行增删改查等操作,由于笔者也是刚接触,对其中的一些原由也不甚了解,若有错误之处,敬请指 ...

  4. 利用scrollintoview方法模拟聊天室收到新消息

    这段时间再写一个聊天的功能,基本的原理已经通了,剩下的就是细化功能和实现了.原理通了不代表就能解决了这个问题,今天就遇到了一个小问题,就是在接收到新的消息以后,最新的消息不能显示在消息区域,而是跑到了 ...

  5. 左侧固定,右侧自适应的布局方式理解margin负值理论

    一.浮动布局 1.先让固定宽度的div浮动!使其脱离文档流.2.margin-left的值等于固定div的宽度相等. .aside{ float: left; width: 200px; backgr ...

  6. Win10操作系统下Oracle VM VirtualBox6.0加载磁盘提示“发现无效设置”的解决方法(包括“不能桥接网卡”问题的解决方法)

    自从电脑换成Win10操作系统后,想借助VMBox处理一些事情,但是遇到了不能桥接网卡的问题,还以为是程序坏了,于是卸载重新安装,但是不行.接着又尝试在虚拟机里重新安装操作系统,还是不行. 然后百度了 ...

  7. Several ports (8005, 8080, 8009) required by Tomcat v9.0 Server at localhost

    Several ports (8005, 8080, 8009) required by Tomcat v9.0 Server at localhost 问题:Tomcat服务器的端口被占用 解决: ...

  8. 基于raspberry搭建个人web server

    树莓派系统介绍 安装操作系统及网络\远程控制配置 安装常用软件 构建web服务器(nginx + php + sqlite) 构建web服务器(appach+mysql+php) 构建NAS服务器 其 ...

  9. python正则表达式模块re

    正则表达式的特殊元素 匹配符号 描述 '.'(点dot) 在默认模式下,它匹配除换行符之外的任何字符.如果指定了DOTALL标志,则匹配包括换行符在内的任何字符 '^'(Caret) 匹配以字符串开头 ...

  10. c/c++ 多线程 std::lock

    多线程 std::lock 当要同时操作2个对象时,就需要同时锁定这2个对象,而不是先锁定一个,然后再锁定另一个.同时锁定多个对象的方法:std::lock(对象1.锁,对象2.锁...) 额外说明: ...