h5 canvas 多张图片合成并保存到手机相册

需求:多张图片合成一张并下载

思路:

1.htmlDom转为canvas

2.toDataUrl() 可将canvas转为base64格式

3.创建a标签,利用a标签的download属性触发click事件,实现下载

 

先来用两张本地图片合成:

1
2
3
4
5
6
data() {
    return {
      img1: require('../../../assets/images/clock/111/he-bg.png'),
      img2: require('../../../assets/images/clock/111/timg.png'),
    }
  },

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
picTogether() {
    var bg =document.getElementById("bg");
    var w = bg.width;
    var h = bg.height;
    var myImage = new Image();
    //背景图片 你自己本地的图片或者在线图片
    myImage.src = this.img1; 
    myImage.setAttribute('crossOrigin', 'anonymous');
 
    myImage.onload = ()=>{
      var canvas = document.createElement('canvas');
      canvas.width = w;
      canvas.height = h;
      var ctx=canvas.getContext("2d");
      ctx.drawImage(bg, 0, 0, ctx.canvas.width, ctx.canvas.height);
 
      var img= new Image();
      img.src= this.img2;
      img.onload = () => {
        ctx.drawImage(img, 15, 120, ctx.canvas.width-30, ctx.canvas.height/2+100);
        this.downUpload('海报.png', canvas.toDataURL("image/png"));
      }
    }
  },

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
downUpload(fileName,content) {
    let aLink = document.createElement('a');
    let blob = this.base64ToBlob(content); //new Blob([content]);
     
    let evt = document.createEvent("HTMLEvents");
    //initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
    evt.initEvent("click", true, true);
    aLink.download = fileName;
    aLink.href = URL.createObjectURL(blob);
    this.savePicHref(aLink.href)
    aLink.click()
  },
  //base64转blob
  base64ToBlob(code) {
    let parts = code.split(';base64,');
    let contentType = parts[0].split(':')[1];
    let raw = window.atob(parts[1]);
    let rawLength = raw.length;
 
    let uInt8Array = new Uint8Array(rawLength);
 
    for (let i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], {type: contentType});
  },

 

两张本地图片合成和下载貌似做好了,如果图片换成用户上传的图片呢?如果不止两张图片呢?

如果是上传到服务器的图片,那么合成会存在跨域的问题,解决是把上传到服务器端图片下载到本地

1
2
3
4
5
_downloadImg() {
    downloadImg({"fileName":this.fileName}).then(res =>{
      this.upImg = res.datas.fileContent
    })
  },

 

如果是多张图片合成,那么就一张张的画,也就是等图片onload成功后处理,这里用的是函数自调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
picTogether(){
      var self = this;
      var imgsrcArray = [
        require('../../../assets/images/clock/111/clock-day2.png'),
        this.upImg,
        require('../../../assets/images/clock/111/wenzi.png'),
        require('../../../assets/images/clock/111/bo1.png')
      ];
      var bg =document.getElementById("bg");
      var w = bg.width;
      var h = bg.height;
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      canvas.width = w;
      canvas.height = h;
       
      var imglen = imgsrcArray.length;
      var drawimg = (function f(n){
        if(n < imglen){
          var img = new Image();
          img.crossOrigin = 'Anonymous'; //解决跨域问题
          img.onload = function(){
            if(n == 0){
              ctx.drawImage(img,0,0,ctx.canvas.width, ctx.canvas.height);
            }else if(n == 1){
              ctx.drawImage(img,25,100,ctx.canvas.width-50,ctx.canvas.height-230);
            } else if(n==2){
              ctx.drawImage(img,200,65,170,100);
            } else{
              ctx.drawImage(img,0,430,ctx.canvas.width,165);
              ctx.font="16px Arial";
              ctx.fillText(`${self.fullName}`,20,480);
              ctx.fillStyle ="#A92E02";
              ctx.fillText(`连续打卡第 ${self.userInfo.num} 天`,20,505);
            }
            f(n+1);
          }
          img.src = imgsrcArray[n];
        }else{
          self.downUpload('海报.png', canvas.toDataURL("image/png"));
        }
      })(0);
    },

  

到这里多张图片合成也做好了,也没有跨域问题了,pc端下载也没问题,

但是手机端去操作发现,保存图片没反应,相册也没有,

行不通,改变思路,用长按保存来做:

ios长按保存可以成功,查看相册也成功保存了合成的图片,

但是安卓手机,长按有菜单提示,但是保存的时候,提示“保存图片到手机失败”,查阅资料发现

安卓手机不支持blob格式的图片保存,

既然这种格式不支持,是不是其他格式可以支持呢?

答案是可以的。

可以把之前生成的base64格式转为jpg或png格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
downUpload(fileName,content) {
      this.downLoadImage(content)
},
 downLoadImage(content) {
      let form = new FormData()  // FormData 对象
      let bl = this.base64ToBlob(content)
      form.append("file", bl, "file_"+ Date.parse(new Date())+".jpg")
      this._postImg(form);
 },_postImg(file) {
      postImg(file).then(res => {
        let imgSrc = process.env.BASE_API + this.imgPathMid + res.datas[0].relativePath
        console.log(imgSrc)
      })
  }

 这样手机端长按保存图片就可以了,ios和安卓都能保存。

 

posted @   王大师  阅读(1893)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示