vue.js3:用html2canvas把html转canvas图片(html2canvas@1.4.1 / vue@3.2.37)

一,安装html2canvas

1,官网:
https://html2canvas.hertzen.com/

如图:

代码站:
https://github.com/niklasvh/html2canvas
2,通过npm安装
liuhongdi@lhdpc:/data/vue/touch$ npm install --save html2canvas
 
added 5 packages in 4s
3,查看已安装的html2canvas库的版本
liuhongdi@lhdpc:/data/vue/touch$ npm list html2canvas
touch@0.1.0 /data/vue/touch
└── html2canvas@1.4.1

说明:刘宏缔的架构森林是一个专注架构的博客,

网站:https://blog.imgtouch.com
原文: https://blog.imgtouch.com/index.php/2023/06/03/vue-js3-yong-html2canvas-ba-html-zhuan-canvas-tu-pian/

         对应的源码可以访问这里获取: https://github.com/liuhongdi/
         或: https://gitee.com/liuhongdi

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,js代码:

<template>
  <div>
    <div style="width:800px;margin: auto;display: flex;flex-direction: column;">
      <div>请选择上传图片:
        <input type="file" id="back" ref="backfile" accept="image/*" @change="handleFile" /></div>

      <div id="imgContainer" style="position: relative;margin-left:150px;margin-top:10px;width:500px;height:500px;overflow: hidden;background: lightgray;" >
        <div id="imgDiv">
        <img id="img" :src="imgSrc" style="" />
          <div id="text"
               :style="{
                  width:'600px',
                  height:'200px',
                  position: 'absolute',
                  left:'50px',
                  top:'50px',
                  width: '300px',
                   height: 'auto',
                   fontSize:fontSizeValue+'px',
                   color:colorValue,
                   fontStyle:styleValue,
                   fontWeight:weightValue,
                   opacity:opacityValue,
                   textAlign:alignValue }">这是一个可编辑的信息,测试思源的字体文件</div>
        </div>
      </div>
      <div>
        字号: <el-input-number
          v-model="fontSizeValue"
          class="mx-4"
          :min="10"
          :max="100"
          controls-position="right"
          @change="fontSizeChange"
      /><br/>
        颜色:<el-color-picker v-model="colorValue" @active-change="setColor" /><br/>
        <span>透明度:</span><el-slider v-model="opacityDispValue" :min="0" :max="100" @input="setOpacity" style="width:300px;" /><br/>
        <button @click="weight">加粗</button>
        <button @click="style">斜体</button>
      </div>

      <div id="dpiBtn" style="display: none;">
        <input type="button" value="保存图片" @click="makeCanvas" />
      </div>
    </div>
  </div>
</template>

<script>
import {ref} from "vue";
import html2canvas from "html2canvas"

export default {
  name: "ImageText",
  setup() {
    //图片的原宽高
    const imgWidth = ref(0);
    const imgHeight = ref(0);
    //图片内容
    const imgSrc = ref("");
    //选中的图片文件
    const imgFile = ref();
    //选中图片后的处理
    const handleFile = () => {
      let filePaths = window.event.target.files;
      //清空原有缩略图
      if (filePaths.length === 0) {
        //未选择,则返回
        return
      }
      //把新选中的图片加入数组
      imgFile.value = filePaths[0];
      imgSrc.value = URL.createObjectURL(imgFile.value);
      let reader = new FileReader();
      reader.readAsDataURL(imgFile.value);
      reader.onload = () =>{
        //显示图片
        imgSrc.value = reader.result;
        //得到宽高
        let img = new Image();
        img.src= reader.result;
        img.onload = () => {
          //保存宽高
          imgWidth.value = img.width;
          imgHeight.value = img.height;

          if (img.width >= img.height) {
            let rate = 500 / img.width;

            let left = (500-img.width) / 2;
            let top = (500 -img.height) / 2;

            let styleStr =  'display:block;width:100%;height:100%;';

            document.getElementById('img').style =  styleStr;

            let styleDivStr = 'position:absolute;width:'+img.width+'px;height:'+img.height+'px;transform:scale('+rate+');left:'+left+'px;display: block;top:'+top+'px;';
            document.getElementById('imgDiv').style =  styleDivStr;

          } else {
            let rate = 500 / img.height;

            let left = (500-img.width) / 2;
            let top = (500 -img.height) / 2;
            let styleStr =  'display: inline-block;width:100%;height:100%;';
            document.getElementById('img').style =  styleStr;

            let styleDivStr = 'position:absolute;width:'+img.width+'px;height:'+img.height+'px;transform:scale('+rate+');left:'+left+'px;display: block;top:'+top+'px;';
            document.getElementById('imgDiv').style =  styleDivStr;
          }
          document.getElementById('dpiBtn').style.display="";
        }
      }
    }

    //对齐
    const alignValue = ref("left");

    //倾斜
    const styleValue = ref("normal");
    const style = () => {
      if (styleValue.value == 'normal') {
        styleValue.value ='italic'
      } else {
        styleValue.value ='normal'
      }
    }
    //加粗
    const weightValue = ref("normal");
    const weight = () => {
      if (weightValue.value == 'normal') {
        weightValue.value ='bold'
      } else {
        weightValue.value ='normal'
      }
    }
    //透明度
    const opacityValue = ref(1);
    const opacityDispValue = ref(100);
    const setOpacity = (value) => {
      opacityValue.value = value / 100;
    }

    //颜色
    const colorValue = ref("#2c3e50");
    const setColor = (value) => {
      colorValue.value = value;
    }
    //字号
    const fontSizeValue = ref(38);
    const fontSizeChange = (value) =>{
      fontSizeValue.value = value;
    }

    //把编辑的文字部分保存成图片
    const makeCanvas = () => {
      html2canvas(document.getElementById('text'),{
        onclone: function(documentClone){
          documentClone.getElementById('imgDiv').style.transform = 'scale(1)';
        }
      }).then(function(canvas){
        downPngByCanvas(canvas);
      });
    }

    //下载图片
    const downPngByCanvas = (canvas) => {
      var oA = document.createElement("a");
      let time = timeFormat();
      oA.download = "img_"+time+'.png';// 设置下载的文件名,默认是'下载'
      oA.href = canvas.toDataURL("image/png").replace('image/png', 'image/octet-stream');

      document.body.appendChild(oA);
      oA.click();
      oA.remove(); // 下载之后把创建的元素删除
    }
    //补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 {
         imgSrc,
         handleFile,
         alignValue,
         style,
         styleValue,
         weight,
         weightValue,
         opacityValue,
         opacityDispValue,
         setOpacity,
         colorValue,
         setColor,
         fontSizeValue,
         fontSizeChange,

         makeCanvas,
       }
  }
}
</script>

<style scoped>
</style>

三,测试效果:

转canvas后:

四,查看vue框架的版本:

root@lhdpc:/data/vue/imgtouch# npm list vue
imgtouch@0.1.0 /data/vue/imgtouch
├─┬ @vue/cli-plugin-babel@5.0.6
│ └─┬ @vue/babel-preset-app@5.0.6
│   └── vue@3.2.37 deduped
└─┬ vue@3.2.37
  └─┬ @vue/server-renderer@3.2.37
    └── vue@3.2.37 deduped

 

posted @ 2022-11-13 08:09  刘宏缔的架构森林  阅读(934)  评论(0编辑  收藏  举报