vue.js3: 多张图片合并(vue@3.2.37)

一,安装用到的第三方库

1,安装:

liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm i -S vuedraggable@next
 
added 2 packages in 11s

2,查看已安装的版本:

liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm list vuedraggable@next
image2pdf@0.1.0 /data/vue/pdf/image2pdf
└── vuedraggable@4.1.0

说明:此第三方库仅供在操作时拖动排序使用,与图片的合并无关

二,js代码:

<template>
<div>
  <div style="width: 800px;margin: auto;">
    <div style="margin-top: 10px;">
      选择图片(可多选):
      <input type="file" ref="hiddenfile" accept="image/*" multiple @change="handleFile" class="hiddenInput" />
    </div>

    <div style="width:400px;margin: auto;margin-top: 10px;">
      <div style="width:400px;font-size:12px;">可以拖动图片改变顺序</div>
      <draggable
          :list="selFiles"
          item-key="id"
          class="list-group"
          ghost-class="ghost"
          @start="dragging = true"
          @end="dragging = false"
      >
        <template #item="{ element,index }">
          <div class="list-group-item">
            <img class="fg" :id="'fg'+element.id" :src="element.fileimg" style="width:400px;display:block;" />
            <div @click="del(index)"
                 style="width:40px;height:40px;position: absolute;top:0px;right:0px;">
              <el-icon style="font-size: 20px;color:white;opacity:0.8;width:40px;height:40px;">
                <Delete />
              </el-icon>
            </div>
          </div>
        </template>
      </draggable>
    </div>
    <div>
      <el-button ref="downButtonRef" :disabled="buttonEnable === true  ?  false : true" type="info" plain
                 @click="down" style="width:400px;margin-top: 10px;">合并图片并下载</el-button>
    </div>
    
  </div>
</div>
</template>

<script>
import {ref} from "vue"
import draggable from "vuedraggable";
export default {
  name: "ImageMerge",
  components: {
    draggable,
  },
  setup() {
    //最大高度和最大宽度
    let maxWidth = 0;
    let maxHeight = 0;
    //选中的图片文件,保存在数组中
    const selFiles = ref([]);
    //得到各图片的最大高度和最大宽度
    const getImgMaxWidthHeight = () => {
      //let allHeight = 0;
      for( var i=0;i<selFiles.value.length; i++ ){
        let one = selFiles.value[i];
        //得到高度
        let img = document.getElementById("fg"+one.id);
        let width = img.naturalWidth;
        let height = img.naturalHeight;
        console.log("width:"+width+";height:"+height);
        if (width>maxWidth) {
            maxWidth = width;
        }
        if (height > maxHeight) {
          maxHeight = height;
        }
      }
      console.log("maxWidth:"+maxWidth+";maxHeight:"+maxHeight);
    }

    //垂直方向合并时,得到高度:
    const getImgDestHeight = () => {
      let allHeight = 0;
      for( var i=0;i<selFiles.value.length; i++ ){
        let one = selFiles.value[i];
        //得到高度
        let img = document.getElementById("fg"+one.id);
        let width = img.naturalWidth;
        let height = img.naturalHeight;
        let destHeightOne = (maxWidth * height) / width;
        allHeight = allHeight+destHeightOne;
      }
      console.log("allHeight:"+allHeight);
      return allHeight;
    }
    
    //下载pdf
    const down = async () => {
      getImgMaxWidthHeight();
      
      //得到合并后图片的高度
      let destHeight = getImgDestHeight();
      console.log("destHeight:"+destHeight);

      //生成合并后图片
      const canvas = document.createElement('canvas')
      canvas.width = maxWidth;
      canvas.height = destHeight;
      const context = canvas.getContext('2d');

      let top = 0;
      //合并图片
      for( var i=0;i<selFiles.value.length; i++ ) {
        console.log(i);
        let one = selFiles.value[i];
        //得到当前图片的高度
        let img = document.getElementById("fg"+one.id);
        let width = img.naturalWidth;
        let height = img.naturalHeight;
        let destHeightOne = (maxWidth * height) / width;
        context.drawImage(img, 0, top, maxWidth, destHeightOne);
        top = top+destHeightOne;
      }
      //下载图片
      downJpgByCanvas(canvas);
    }
    
    //下载图片
    const downJpgByCanvas = (canvas) => {
      var oA = document.createElement("a");
      let time = timeFormat();
      oA.download = "img_"+time+'.jpg';// 设置下载的文件名,默认是'下载'
      oA.href = canvas.toDataURL("image/jpeg");
      document.body.appendChild(oA);
      oA.click();
      oA.remove(); // 下载之后把创建的元素删除
    }
    
    //选中图片时,把图片添加到数组
    const handleFile = (e) => {
      let filePaths = e.target.files;
      //清空原有缩略图
      if (filePaths.length === 0) {
        //未选择,则返回
        return
      } else {
        //清空数组中原有图片
        selFiles.value.length = 0;
      }
      //把新选中的图片加入数组
      for( var i=0;i<filePaths.length; i++ ){
        let file = filePaths[i];
        var reader = new FileReader();
        reader.readAsArrayBuffer(file);
        //reader.
        let one = {
          id:i,
          fileimg:URL.createObjectURL(file),  //预览用
          file:file,
        }
        selFiles.value[i] = one;
      }
      setButton();
    }

    //设置下载button是否可用
    const buttonEnable = ref(false);
    const setButton = () => {
      console.log("files length:"+selFiles.value.length);
      if (selFiles.value.length>0) {
        buttonEnable.value = true;
      } else {
        buttonEnable.value = false;
      }
    }
    
    //补0
    const add0 = (m) => {
      return m<10?'0'+m:m
    }
    //格式化时间
    const timeFormat = ()=>{
      var time = new Date();
      var y = time.getFullYear();
      var m = time.getMonth()+1;
      var d = time.getDate();
      var h = time.getHours();
      var mm = time.getMinutes();
      var s = time.getSeconds();
      let res = y+add0(m)+add0(d)+add0(h)+add0(mm)+add0(s);
      return res;
    }
    
    return {
      down,
      handleFile,
      selFiles,
      buttonEnable,
    }
  }
}
</script>

<style scoped>

</style>

三,测试效果:

界面:

合并后的图片:

说明:刘宏缔的架构森林—专注it技术的博客,
网址:https://imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/06/02/vue-js3-duo-zhang-tu-pian-he-bing-vue-3-2-37/
代码: https://github.com/liuhongdi/https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com

四,查看vue框架的版本:

liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm list vue
image2pdf@0.1.0 /data/vue/pdf/image2pdf
├─┬ @vue/cli-plugin-babel@5.0.8
│ └─┬ @vue/babel-preset-app@5.0.8
│   ├─┬ @vue/babel-preset-jsx@1.3.0
│   │ └── vue@3.2.37 deduped invalid: "2.x" from node_modules/@vue/babel-preset-jsx
│   └── vue@3.2.37 deduped
└─┬ vue@3.2.37
  └─┬ @vue/server-renderer@3.2.37
    └── vue@3.2.37 deduped
QR:vue.js3: 多张图片合并(vue@3.2.37)

发表回复