最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • js实现图片合并下载(附代码)

    正文概述 掘金(豆包君)   2021-07-04   493

    js实现图片合并下载(附代码)

    本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

    目录

    • 前言

    • 正文

      • 一、实现步骤
      • 二、代码实现
    • 总结

    • 参考文档

    前言

     前些日子碰到一个需求,关于图像合并下载并转换为文件格式。综合考虑,决定使用Canvas实现,本文以记录实现流程,供大家参考。

     需求如下:

     用户上传图片,或者是传入图片url列表,根据图片数量合成新图片,一张平铺,二张并列,三张品字形,四张田字形,最后返回Blob对象或者Base64格式。

    正文

    一、实现步骤

     实现步骤如下:

    1. 获取用户上传图片列表,支持用户手动上传及传入图片url列表
    2. 处理图片列表。如果用户手动上传的图片,直接获取元素对象使用;对于图片url列表需要使用new Image()处理成对象列表再使用;
    3. 生成一块canvas画布,使用drawImage方法按照一定位置把我们的拓片画上去。
    4. 将生成的canvas画布按照所需格式返回(Blob对象或者Base64)
    5. 利用a标签实现下载

    二、代码实现

     因为是蛮简单的一个功能实现,所以直接贴代码了。

    Demo代码:

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <title>实现图片合并下载</title>
    </head>
    <style>
      .img_style {
        width: 30px;
        height: auto;
      }
    </style>
    
    <body>
    
      <fieldset>
        <input type="file" onchange="imageUpload(this,'#firstImg')">
        <img id="firstImg" class="img_style">
        <legend>上传图1</legend>
      </fieldset>
      <fieldset>
        <input type="file" onchange="imageUpload(this,'#secondImg')">
        <img id="secondImg" class="img_style">
        <legend>上传图2</legend>
      </fieldset>
      <fieldset>
        <input type="file" onchange="imageUpload(this,'#thirdImg')">
        <img id="thirdImg" class="img_style">
        <legend>上传图3</legend>
      </fieldset>
      <fieldset>
        <input type="file" onchange="imageUpload(this,'#fourthImg')">
        <img id="fourthImg" class="img_style">
        <legend>上传图4</legend>
      </fieldset>
    
    
      <fieldset>
        <button onclick="clickPreview()">点击合成</button>
        <button onclick="clickDownload()">点击下载</button>
      </fieldset>
      <div id='base64ObjBox'>
        <p>生成base64文件</p>
      </div>
      <div id='blobObjBox'>
        <p>生成file文件</p>
      </div>
      <!-- <canvas id="myCanvas" width="200" height="200" style="border:1px solid #c3c3c3;"></canvas> -->
    
    </body>
    <script>
      /**
      * @description 合并图片并返回文件方法
      * @param {Array} imgsList  图片列表(url或者对象),必填
      * @param {Boolean} isFileObj  是否返回文件对象,默认false,返回base64
      * @param {Number} canvasWidth  生成图片宽度,默认200px
      * @param {Number} canvasHeight  生成图片高度,默认200px
      * @return  合并成的图片文件,base64或者file
      */
    
      async function returnPicMerge(imgsList, isFileObj = false, canvasWidth = 200, canvasHeight = 200) {
        // 图片列表为空或者非数组,直接返回
        if (!Array.isArray(imgsList) || imgsList.length === 0) {
          return
        }
        // 初始化图片列表
        let imgEles = []
        if (typeof (imgsList[0]) === 'object') {
          // 图片对象列表直接使用
          imgEles = imgsList
        } else {
          // 图片链接列表需要处理成对象列表
          let imgSrcs = imgsList.map(item => {
            let image = new Image()
            image.src = item + '?v=' + Math.random() // 处理缓存
            image.crossOrigin = '*' // 支持跨域图片
            return new Promise(function (resolve, reject) {
              image.onload = function () {
                resolve(image)
              }
            //   image.onerror = function() {
            //     let defaultImg = new Image();
            //     defaultImg.src = Config.publicTfsUrl + "/" + Config.defaultImg + '?v=' + Math.random();
            //     defaultImg.crossOrigin = '*' // 支持跨域图片
            //     defaultImg.onload = () => {
            //         resolve(defaultImg);
            //     }
            });
          });
          imgEles = await Promise.all(imgSrcs);
        }
    
        // 初始化图片宽高及位置坐标
        let imgWidth = canvasWidth
        let imgHeight = canvasHeight
        let xCoordinate = 0
        let yCoordinate = 0
    
        // 创建canvas对象
        let canvas = document.createElement('canvas');
        canvas.width = canvasWidth;
        canvas.height = canvasHeight;
    
        let ctx = canvas.getContext("2d");
    
        // 填充背景色
        // ctx.fillStyle = "#87CEEB";
        // ctx.fillRect(0, 0, canvasWidth, canvasHeight);
    
    
        if (imgEles.length === 1) {
          // 绘制图片,一张图铺满
          ctx.drawImage(imgEles[0], xCoordinate, yCoordinate, imgWidth, imgHeight);
        } else if (imgEles.length === 2) {
          // 两张图并列
          imgWidth = canvasWidth / 2
          imgHeight = canvasHeight/2
          yCoordinate = (canvasHeight - imgHeight) / 2
          imgEles.forEach((item, index) => {
            ctx.drawImage(item, xCoordinate, yCoordinate, imgWidth, imgHeight);
            xCoordinate += imgWidth
          });
        } else if (imgEles.length === 3) {
          // 三张图品字形
          imgWidth = canvasWidth / 2
          imgHeight = canvasHeight / 2
          xCoordinate = (canvasWidth - imgWidth) / 2
          imgEles.forEach((item, index) => {
            if (index === 1) {
              yCoordinate += imgHeight
              xCoordinate = (canvasWidth - imgWidth * 2) / 2
            }
            ctx.drawImage(item, xCoordinate, yCoordinate, imgWidth, imgHeight);
            xCoordinate += imgWidth
          });
        } else if (imgEles.length === 4) {
          // 四张图田字形
          imgWidth = canvasWidth / 2
          imgHeight = canvasHeight / 2
          imgEles.forEach((item, index) => {
            if (index === 2) {
              yCoordinate += imgHeight
              xCoordinate = (canvasWidth - imgWidth * 2) / 2
            }
            ctx.drawImage(item, xCoordinate, yCoordinate, imgWidth, imgHeight);
            xCoordinate += imgWidth
          });
        }
    
        // 返回文件
        if (isFileObj) {
          return new Promise(function (resolve, reject) {
            canvas.toBlob(function (blobObj) {
              resolve(blobObj)
            })
          })
        } else {
          return canvas.toDataURL('image/png')
        }
      }
      // 点击上传图片
      function imageUpload(imgFile, id) {
        let f = imgFile.files[0];//获取上传的图片文件
        let filereader = new FileReader();//新建一个图片对象
        filereader.onload = function (event) {//图片加载完成后执行的函数
          let srcpath = event.target.result;//这里获取图片的路径(图片会被转为base6格式)
          document.querySelector(id).setAttribute("src", srcpath);//将获取的图片插入到相应的图片元素里
        };
        filereader.readAsDataURL(f);//读取图片(将插入的图片读取显示出来)
      }
      function getImgSize(str) {
        //获取base64图片大小,返回KB数字
        // var str = base64url.replace('data:image/jpeg;base64,', '');//这里根据自己上传图片的格式进行相应修改
        var strLength = str.length;
        var fileLength = parseInt(strLength - (strLength / 8) * 2);
        // 由字节转换为KB
        var size = "";
        size = (fileLength / 1024/1024).toFixed(2);
        
        return parseInt(size);
    
      }
    
      // 点击预览
      async function clickPreview() {
        // 获取图片列表
        let imgsList = Array.from(document.getElementsByClassName("img_style")).filter(item => {
          if (item.src) {
            return item
          }
        });
        // 如果用户没有上传文件,初始化赋值
        if (imgsList.length === 0) {
          imgsList = [
            'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3080163631,1117627422&fm=26&gp=0.jpg',
            'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fyouimg1.c-ctrip.com%2Ftarget%2Ftg%2F374%2F780%2F501%2F559858dc54b34a979c8816a8377fcf01.jpg&refer=http%3A%2F%2Fyouimg1.c-ctrip.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625888610&t=9a05b684a1f8426b8f3ccddc236ec271',
          ]
        }
    
        // 调用方法,获取base64
        let base64Obj = await returnPicMerge(imgsList)
    
        // 调用方法,获取blob
        let blobObj = await returnPicMerge(imgsList, true,200,200)
    
        var strLength = base64Obj.length;
        var fileLength = parseInt(strLength - (strLength / 8) * 2);
        console.log('base64Obj', base64Obj)
        console.log('base64Obj大小', fileLength / 1024/1024)
    
        console.log('blobObj', blobObj)
        console.log('blobObj大小', blobObj.size/1024/1024)
        
    
        let image1, image2
        let base64ObjBox = document.getElementById('base64ObjBox');
        let blobObjBox = document.getElementById('blobObjBox');
        // 没有图片元素就创建,有就更新
        if (document.getElementById('image1')) {
          image1 = document.getElementById('image1')
          image1.src = base64Obj
        } else {
          image1 = new Image()
          image1.src = base64Obj
          image1.setAttribute('id', 'image1');
          base64ObjBox.appendChild(image1);
        }
        if (document.getElementById('image2')) {
          image2 = document.getElementById('image2')
          image2.src = window.URL.createObjectURL(blobObj)
        } else {
          image2 = new Image()
          image2.src = window.URL.createObjectURL(blobObj)
          image2.setAttribute('id', 'image2');
          blobObjBox.appendChild(image2);
        }
      }
      // 点击下载
      function clickDownload() {
        let img = document.getElementById("image1");
        let link = document.createElement('a');//创建一个a标签
        link.download = 'my-image-name.jpg';//a标签增加一个download属性,属性值(my-image-name.jpg)就是合成下载后的文件名
        link.href = img.src;//将路径赋给a标签的href
        link.click();//模拟a标签被点击,这样就可以下载了
      }
    
    </script>
    
    </html>
    

    总结

     其实自己实现一些功能也是一个蛮不错的体验。可以加强对一些功能的熟悉以及对一些API的认识,也可以为自己积累一些备用代码,免得如后万一碰到还要耽误时间到处找资料。

     路漫漫其修远兮,与诸君共勉。

    后记:Hello 小伙伴们,如果觉得本文还不错,记得点个赞或者给个 star,你们的赞和 star 是我编写更多更丰富文章的动力!GitHub 地址

    文档协议


    起源地下载网 » js实现图片合并下载(附代码)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元