前端使用upload拍照添加水印并上传

前端拍照添加水印

注:本篇文章使用的是vant UI 的upload上传功能

一、upload 调起摄像头拍照

    <van-uploader
      v-model="fileList"
      :before-read="beforeRead"
      :after-read="afterRead"
      @delete="delImgUrl"
      :max-count="9"
      class="uploader"
      capture="camera"
      accept="image/*"
      preview-image
    >

v-model 绑定图片列表
before-read 上传的前置操作,可做图片压缩
after-read 成功读取upload上传文件的回调,===**在这里添加水印并上传图片给后端,最终返回添加了水印的图片网址。
delete 点击图片删除图标的操作
max-count 限制上传数量
capture=“camera” 调起摄像头(移动端),pc端只能添加本地图片。
accept=“image/*” 允许上传的文件类型
preview-image 图片上传完成后展示预览图

二、使用步骤

1.基础数据

代码如下(示例):

 fileList: [],// [{url:'XXX'},{url:'XXX'}]
 wmConfig1: {
        //水印配置1
        font: "microsoft yahei", //字体
        textArray: [], //水印文本内容,允许数组最大长度3 即:3行水印
        density: 1, //密度 建议取值范围1-5   值越大,水印越多,可能会导致水印重叠等问题,慎重!!!
        texttranslate: [40, 80],
        position: "top",
},
wmConfig2: {
        //水印配置2
        font: "microsoft yahei",
        textArray: [], 
        density: 1, 
        texttranslate: [40, 580],
        position: "bom",
},

2.具体操作,

这里将文件写成了组件
注:photoUrl 是父组件传值格式:photoUrl :“XXX;XXX;XXX”。
其中XXX代表每一个图片地址。所以子组件需要修改为fileList:[{url:‘XXX’},{url:‘XXX’}]数组的格式来显示图片。

代码如下(示例):

<template>
  <div>
    <van-uploader
      v-model="fileList"
      :after-read="afterRead"
      :disabled="!isCanEdit"
      :deletable="isCanEdit"
      @delete="delImgUrl"
      :max-count="9"
      class="uploader"
      capture="camera"
      accept="image/*"
      name="pictureFile"
      preview-image
    >
      <!-- <span>点击调用摄像头进行拍摄capture="camera"  accept="image/*"</span> -->
    </van-uploader>
  </div>
</template>

<script>
import moment from "moment";
import Compressor from "compressorjs";
export default {
  props: {
    photoUrl: {
      type: String,
    },
    isCanEdit: {
      type: Boolean,
    },
    dataParams: {
      type: Object,
    },
    ind: {
      type: Number,
    },
  },
  created() {
    this.userId = sessionStorage.getItem("userId");
  },
  data() {
    return {
      userId: "",
      fileList: [],
      wmConfig1: {
        //水印配置1
        font: "microsoft yahei", //字体
        textArray: [], //水印文本内容,允许数组最大长度3 即:3行水印
        density: 1, //密度 建议取值范围1-5   值越大,水印越多,可能会导致水印重叠等问题,慎重!!!
        texttranslate: [40, 80],
        position: "top",
      },
      wmConfig2: {
        //水印配置2
        font: "microsoft yahei", //字体
        textArray: [], //水印文本内容,允许数组最大长度3 即:3行水印
        density: 1, //密度 建议取值范围1-5   值越大,水印越多,可能会导致水印重叠等问题,慎重!!!
        texttranslate: [40, 580],
        position: "bom",
      },
    };
  },
  watch: {
    // 监听父组件数据变化,数据回显
    photoUrl: {
      handler(newVal) {
        this.fileList = [];
        if (newVal && newVal.length > 0) {
          let arr = newVal.split(";");
          arr.map((item) => {
            // 数据回显
            this.fileList.push({
              url: item,
            });
          });
        }
      },
      immediate: true,
    },
  },
  methods: {
    async afterRead(file) {
      file.status = "uploading";
      file.message = "上传中...";

      let base64 = file.content;
      this.setWMConfig1();
      this.setWMConfig2();
      let res = await this.base64AddWaterMaker(base64); //加水印的重点就是这个(小冰)
      file.file.content = res;

      file.file = this.base64ImgtoFile(res); //base64转图片

      //  向后端 请求,返回url地址
      this.uploadImg(file.file);

      setTimeout(() => {
        file.status = "succes";
      }, 300);
    },
    
    // 水印文字配置,可配置多个setWMConfig1、setWMConfig2...
    setWMConfig1() {
      // 获取拍照时间
      let weekStr = this.getWeekday();
      let dateStr = moment().format("YYYY/MM/DD");
      let timeStr = moment().format("HH:mm:ss");

      this.wmConfig1.textArray.push(weekStr, dateStr, timeStr);
    },
    setWMConfig2() {
      // 获取地址,导购员,门店信息
      this.wmConfig2.textArray.push(
        this.userId || "",
        this.dataParams.addressDetail || "",
        this.dataParams.storeMDMCode || ""
      );
    },
   
    // 1.添加水印
    base64AddWaterMaker(base64Img) {
      let that = this;
      return new Promise((resolve, reject) => {
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        const img = new Image();
        let resultBase64 = null;
        img.onload = function () {
          canvas.width = img.width;
          canvas.height = img.height;
          //canvas绘制图片,0 0  为左上角坐标原点
          ctx.drawImage(img, 0, 0);
          //写入水印
          that.drawWaterMark(ctx, img.width, img.height, that.wmConfig1);
          that.drawWaterMark(ctx, img.width, img.height, that.wmConfig2);
          resultBase64 = canvas.toDataURL("image/png");
          if (!resultBase64) {
            reject();
          } else {
            resolve(resultBase64);
          }
        };
        img.src = base64Img;
      });
    },
    // 2.绘制水印
    drawWaterMark(ctx, imgWidth, imgHeight, wmConfig) {
      // fontSize 文字大小, texttranslate水印位置
      let fontSize;
      if (imgWidth >= 3456) {
        fontSize = 80;
        wmConfig.texttranslate[0] = 80;
        wmConfig.texttranslate[1] =
          wmConfig.position == "top" ? 120 : imgHeight - 400;
      } else if (imgWidth >= 2700) {
        wmConfig.texttranslate[0] = 70;
        wmConfig.texttranslate[1] =
          wmConfig.position == "top" ? 100 : imgHeight - 370;
        fontSize = 70;
      } else if (imgWidth >= 2000) {
        fontSize = 60;
        wmConfig.texttranslate[0] = 60;
        wmConfig.texttranslate[1] =
          wmConfig.position == "top" ? 80 : imgHeight - 350;
      } else if (imgWidth >= 1436) {
        fontSize = 50;
        wmConfig.texttranslate[0] = 50;
        wmConfig.texttranslate[1] =
          wmConfig.position == "top" ? 80 : imgHeight - 300;
      } else if (imgWidth >= 800) {
        fontSize = 40;
        wmConfig.texttranslate[0] = 40;
        wmConfig.texttranslate[1] =
          wmConfig.position == "top" ? 80 : imgHeight - 250;
      } else if (imgWidth >= 500) {
        fontSize = 30;
        wmConfig.texttranslate[0] = 30;
        wmConfig.texttranslate[1] =
          wmConfig.position == "top" ? 80 : imgHeight - 200;
      } else {
        fontSize = 26;
        wmConfig.texttranslate[0] = 30;
        wmConfig.texttranslate[1] =
          wmConfig.position == "top" ? 50 : imgHeight - 200;
      }

      ctx.fillStyle = "white";
      ctx.font = `${fontSize}px ${wmConfig.font}`;
      ctx.lineWidth = 1;
      ctx.fillStyle = "rgba(255,255,255,1)";
      ctx.textAlign = "left";
      ctx.textBaseline = "middle";
      //文字坐标
      const maxPx = Math.max(imgWidth, imgHeight);
      const stepPx = Math.floor(maxPx / wmConfig.density);
      let arrayX = [0]; //初始水印位置 canvas坐标 0 0 点
      while (arrayX[arrayX.length - 1] < maxPx / 2) {
        arrayX.push(arrayX[arrayX.length - 1] + stepPx);
      }
      arrayX.push(
        ...arrayX.slice(1, arrayX.length).map((el) => {
          return -el;
        })
      );

      for (let i = 0; i < arrayX.length; i++) {
        for (let j = 0; j < arrayX.length; j++) {
          ctx.save();
          ctx.translate(0, 0); //画布旋转原点 移到 图片中心
          ctx.translate(...wmConfig.texttranslate); //水印位置
          // ctx.rotate(-Math.PI / 5);//水印旋转
          if (wmConfig.textArray.length > 3) {
            wmConfig.textArray = wmConfig.textArray.slice(0, 3);
          }
          wmConfig.textArray.forEach((el, index) => {
            let offsetY = fontSize * index + 2;
            ctx.fillText(el, arrayX[i], arrayX[j] + offsetY);
          });
          ctx.restore();
        }
      }
    },
    // 3.base64转文件
    base64ImgtoFile(dataurl, filename = "file") {
      let arr = dataurl.split(",");
      let mime = arr[0].match(/:(.*?);/)[1];
      let suffix = mime.split("/")[1];
      let bstr = atob(arr[1]);
      let n = bstr.length;
      let u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], `${filename}.${suffix}`, {
        type: mime,
      });
    },
    // 4.上传给后端,图片存到数据库,并转化为前端需要的图片地址。
    uploadImg(file) {
      let formData = new FormData();
      formData.append("pictureFile", file);//请求体 pictureFile:图片文件
      this.$axios({
        url: "???这里是后端提供的地址" + this.userId,//地址:"XXX?userId=",入参:this.userId
        method: "post",
        data: formData,
        responseType: "*",
      })
        .then((res) => {
          //这里的url为后端接口
          if (res.data.code == 200) {
            let url = "";
            if (this.photoUrl.length > 0) {
              url = this.photoUrl + ";" + res.data.msg;
            } else {
              url = res.data.msg;
            }
            this.getImgUrl(url);
          }

          //res 为接口返回值
        })
        .catch(() => {});
    },
    // 点击删除操作
    delImgUrl(e) {
      this.fileList.filter((item) => item == e);
      this.$emit("delImgUrl", this.fileList, this.ind);
      let url = this.$api.moblieTask.deleteImage;
      let param = { pictureUrl: e.url };
      this.$post(url, param).then((res) => {
        console.log("deleteImage", res);
      });
    },
    // 暴露数据,修改父组件数据
    getImgUrl(url) {
      this.$emit("getImgUrl", url, this.ind);
    },
    // 获取当前时间是星期几
    getWeekday(dateStr) {
      const weekDays = [
        "星期日",
        "星期一",
        "星期二",
        "星期三",
        "星期四",
        "星期五",
        "星期六",
      ];

      // const date = new Date(dateStr);
      const date = new Date();

      const weekday = date.getDay();
      return weekDays[weekday];
    },
  },
};
</script>

<style>
</style>

总结

以上就是今天要讲的内容,本文重点是canvas绘图添加水印的使用。

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在uniapp中上传图片/视频并添加水印,可以按照以下步骤: 1. 在前端页面中,添加一个文件上传控件,例如: ```html <template> <div> <input type="file" ref="fileInput" @change="uploadFile"> </div> </template> ``` 2. 在前端编写上传文件的逻辑,可以使用uniapp提供的上传组件,例如: ```js methods: { // 上传文件 uploadFile() { const file = this.$refs.fileInput.files[0] uni.uploadFile({ url: '/upload', filePath: file.tempFilePath, name: 'file', success: (res) => { console.log('上传成功', res) }, fail: (err) => { console.log('上传失败', err) } }) } } ``` 3. 在后端编写一个接口,用于接收上传的文件并添加水印。可以使用Java、PHP等语言实现添加水印的逻辑,下面以Java为例。在接口中,可以使用以下代码实现添加水印: ```java // 获取上传的文件 Part filePart = request.getPart("file"); String fileName = filePart.getSubmittedFileName(); InputStream fileContent = filePart.getInputStream(); // 添加水印 Image image = ImageIO.read(fileContent); Graphics2D g = image.createGraphics(); g.drawImage(image, 0, 0, null); g.setFont(new Font("Arial", Font.BOLD, 30)); g.setColor(Color.RED); g.drawString("Watermark", 10, 30); g.dispose(); // 保存文件到服务器 File file = new File("/path/to/save/" + fileName); ImageIO.write(image, "jpg", file); ``` 4. 在前端接收后端返回的结果,例如: ```js success: (res) => { console.log('上传成功', res) // 处理上传成功的逻辑 }, fail: (err) => { console.log('上传失败', err) // 处理上传失败的逻辑 } ``` 以上是uniapp中上传图片/视频并添加水印的基本步骤,需要注意的是,添加水印时需要使用服务器端的代码实现,客户端无法实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值