VUE-使用canvas和cropperjs简单的图片处理

引入canvas 和cropperjs

$ npm install canvas -s
$ npm install cropperjs -s

代码

<template>
  <div class="hello">
    <!-- 画布 -->
    <div id="huabuDiv">
      <div style="width:1200px;margin-top:60px" title="画图">
        <!--操作 -->
        字体大小:
        <el-select
          size="mini"
          style="width:8%;back-ground:blue;height:28px"
          v-model="fontSize"
          placeholder="请选择字体大小"
        >
          <el-option label="12" value="12"></el-option>
          <el-option label="16" value="16"></el-option>
          <el-option label="20" value="20"></el-option>
          <el-option label="24" value="24"></el-option>
          <el-option label="28" value="28"></el-option>
          <el-option label="32" value="32"></el-option>
          <el-option label="48" value="48"></el-option>
          <el-option label="64" value="64"></el-option> </el-select
        >&nbsp; 每行字数:
        <el-input
          size="mini"
          style="width:8%"
          v-model="fontMount"
          placeholder="请选择每行字数"
        />&nbsp;&nbsp;
        <el-button type="primary" size="mini" @click="shuaxinhuabu"
          >重置</el-button
        >
        <el-button
          type="primary"
          size="mini"
          :disabled="this.canvasIndex == 0"
          @click="changeCanvas(1)"
          >上一步</el-button
        >
        <el-button
          type="primary"
          size="mini"
          :disabled="this.canvasIndex >= this.canvasData.length"
          @click="changeCanvas(2)"
          >下一步</el-button
        >
        <el-button type="primary" size="mini" @click="getType(1)"
          >文字</el-button
        >
        <el-button type="primary" size="mini" @click="getType(2)"
          >椭圆</el-button
        >
        <el-button type="primary" size="mini" @click="getType(3)"
          >方框</el-button
        >
        <el-button type="primary" size="mini" @click="xuanzhuan(1)"
          >左旋</el-button
        >
        <el-button type="primary" size="mini" @click="xuanzhuan(2)"
          >右旋</el-button
        >

        <el-button type="primary" size="mini" @click="initCropper()"
          >裁剪</el-button
        >
        <el-button type="primary" size="mini" @click="saveCropImg()"
          >确认</el-button
        >
        <el-button type="primary" size="mini" @click="saveHuabu()"
          >保存</el-button
        >
        <br />
        <!-- 画布 -->
        <canvas
          magin-top=""
          @mousedown="canvasDown"
          @mouseup="canvasUp"
          @click="huoquzuobiao"
          id="myCanvas"
          ref="myCanvas"
          style="z-index: 1;align-content:center;border: 1px solid red;background-color:#ead3d3;"
          >您的浏览器不支持canvas标签。</canvas
        >
        <textarea
          @keyup.enter="luruFont"
          id="fontInput"
          style="z-index: 2;height:30px;display:none;border:2px solid groove;position:absolute;"
        ></textarea>
      </div>
    </div>
  </div>
</template>
        <script>
import Cropper from "cropperjs";
export default {
  name: "JcbgMiddle",
  components: {},
  data() {
    return {
      canvasIndex: 0,
      canvasData: [],
      fontMount: 10,
      // 截图模型
      cropper: "",
      // 画布弹窗
      dialogds: true,
      // 图片地址
      imgUrl: "http://lwww.baidu.com" //图片地址,
      // 文字大小
      fontSize: 16,
      // 文字录入坐标
      intputFontX: "",
      intputFontY: "",
      fontX: "",
      fontY: "",
      // 图片坐标
      picX: "",
      picY: "",
      // 操作类型
      caozuoType: "",
      // 保存的画布
      imgBase64: "",
      imgBeginUrl: "",
      // 画布对象
      canvas: "",
      jiaodu: 0,
      // 截图所需
      beginRec: {
        x: "",
        y: ""
      },
      // 鼠标移动事件
      canvasMoveUse: false,
      // 画布弹窗是否展示
      huatuPic: false,
      // 修改检查图片弹窗
      dialogFormPic: false,
      // 图片模型
      img: ""
    };
  },
  props: ["callbackdata"],
  mounted() {
    // 初始隐藏 dialog 第一次打开无法获取其内元素
    this.dialogds = false;
    this.$nextTick(function() {
      this.shuaxinhuabu();
    });
  },

  methods: {
    // 弹窗关闭之前的确认
    handleClose(done) {
      this.$confirm("确认关闭?")
        .then(_ => {
          done(_);
        })
        .catch(_ => {
          console.log(_);
        });
    },
    // 画布的上一步
    spliceCanvasDaata() {
      let datalength = this.canvasData.length;
      if (this.canvasIndex < datalength) {
        this.canvasData = this.canvasData.splice(0, this.canvasIndex - 1);
        console.log("is use method spliceCanvasData");
        this.canvasIndex--;
      }
    },
    // 画图操作上一步 下一步
    changeCanvas(val) {
      console.log(this.canvasIndex);
      // 上一步
      if (val == 1) {
        if (this.canvasIndex == 1) {
          this.shuaxinhuabu();
          this.canvasIndex--;
        }
        if (this.canvasIndex > 1) {
          this.canvasIndex--;
          let canvasNow = this.canvasData[this.canvasIndex - 1];
          let myCanvas = this.$refs.myCanvas;
          myCanvas.width = canvasNow.width;
          myCanvas.height = canvasNow.height;
          let ctx = myCanvas.getContext("2d");
          ctx.putImageData(canvasNow, 0, 0);
          ctx.save();
        }
      }
      // 下一步
      if (val == 2) {
        this.canvasIndex++;

        let canvasNow = this.canvasData[this.canvasIndex - 1];
        let myCanvas = this.$refs.myCanvas;
        myCanvas.width = canvasNow.width;
        myCanvas.height = canvasNow.height;
        let ctx = myCanvas.getContext("2d");
        ctx.putImageData(canvasNow, 0, 0);
        ctx.save();
      }
    },
    // 初始化截图对象
    initCropper() {
      if (this.cropper != "") {
        this.cropper.destroy();
      }
      var image = this.$refs.myCanvas;
      this.dialogVisible = true;
      var cropper = new Cropper(image, {
        background: false,
        zoomable: false,
        ready: function() {
          self.croppable = true;
        }
      });
      this.cropper = cropper;
    },
    // 保存截图到画布
    saveCropImg() {
      this.imgBeginUrl = this.cropper
        .getCroppedCanvas()
        .toDataURL("image/jpeg");
      var canvas = this.$refs.myCanvas;
      if (canvas.getContext) {
        //获取对应的CanvasRenderingContext2D对象(画笔)
        let ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        //创建新的图片对象
        var img = new Image();
        //指定图片的URL
        //浏览器加载图片完毕后再绘制图片
        img.src = this.cropper.getCroppedCanvas().toDataURL("image/jpeg");
        img.crossOrigin = "anonymous";
        img.onload = function() {
          //以Canvas画布上的坐标(10,10)为起始点,绘制图像
          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(
            img,
            canvas.width / 2 - img.width / 2,
            canvas.height / 2 - img.height / 2
          );
        };
        this.img = img;
        this.canvas = canvas;
        this.cropper.destroy();
        let imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height);
        this.spliceCanvasDaata();
        this.canvasData.push(imgdata);
        this.canvasIndex++;
      }
    },
    // 提交修改
    saveHuabu() {
      const image = document.getElementById("myCanvas");
      image.setAttribute("crossOrigin", "anonymous");
      var src = image.toDataURL("image/png");
      this.imgBase64 = src;
      var blob = this.dataURItoBlob(src);
      let dataform = new FormData();
      dataform.append("jcjgPicFile", blob);
      dataform.append("xiangmuId", this.jcjgPicId);
      this.$axios
        .post("http://www.baidu.com", dataform, {
          "Content-Type": "multipart/form-data"
        })
        .then(response => {
          if (response.data.code == "000000") {
            alert("修改成功");
            this.dialogFormPic = false;
            this.getJianchabaogao();
            this.jcjgPicId = "";
            this.dialogds = false;
          }
        });
    },
    // 转换画布对象为Blob 准备上传的数据
    dataURItoBlob(base64Data) {
      var byteString;
      if (base64Data.split(",")[0].indexOf("base64") >= 0)
        byteString = atob(base64Data.split(",")[1]);
      else byteString = unescape(base64Data.split(",")[1]);
      var mimeString = base64Data
        .split(",")[0]
        .split(":")[1]
        .split(";")[0];
      var ia = new Uint8Array(byteString.length);
      for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
      }
      return new Blob([ia], { type: mimeString });
    },
    //旋转图片的方法
    xuanzhuan(val) {
      let context = this.$refs.myCanvas.getContext("2d");
      this.dialogVisible = true;

      if (val == 1) {
        this.jiaodu += 3;
      }
      if (val == 2) {
        this.jiaodu += 1;
      }
      let canvas = this.$refs.myCanvas;
      context.save();
      let a = canvas.width;
      canvas.width = canvas.height;
      canvas.height = a;
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.translate(canvas.width / 2, canvas.height / 2);
      context.rotate((this.jiaodu / 2) * Math.PI);
      context.translate(-canvas.width / 2, -canvas.height / 2);
      context.drawImage(
        this.img,
        canvas.width / 2 - this.img.width / 2,
        canvas.height / 2 - this.img.height / 2
      );
      context.translate(canvas.width / 2, canvas.height / 2);
      context.rotate((-this.jiaodu / 2) * Math.PI);
      context.translate(-canvas.width / 2, -canvas.height / 2);
      this.canvas = canvas;
      context.restore();
      context.save();
      let imgdata = context.getImageData(0, 0, canvas.width, canvas.height);
      this.spliceCanvasDaata();
      this.canvasData.push(imgdata);
      this.canvasIndex++;
    },
    //鼠标点下的事件
    canvasDown(e) {
      console.log(e.offsetX, e.offsetY);
      this.canvasMoveUse = true;
      // client是基于整个页面的坐标,offset是cavas距离pictureDetail顶部以及左边的距离
      const canvasX = e.offsetX;
      const canvasY = e.offsetY;
      // 记录起始点和起始状态
      this.beginRec.x = canvasX;
      this.beginRec.y = canvasY;
      // this.beginRec.imageData = this.context.getImageData(0, 0, this.width, this.height)
      // 存储本次绘制坐标信息
      let context = this.$refs.myCanvas.getContext("2d");
      context.beginPath();
      context.save();
    },
    //鼠标抬起的事件
    canvasUp(e) {
      const canvasX = e.offsetX;
      const canvasY = e.offsetY;
      let a = (canvasX + this.beginRec.x) / 2;
      let b = (canvasY + this.beginRec.y) / 2;
      let c = (canvasX - this.beginRec.x) / 2;
      if (c < 0) {
        c = -c;
      }
      let d = c / 2;
      let l = canvasX - this.beginRec.x;
      let f = canvasY - this.beginRec.y;
      if (l < 0) {
        l = -l;
      }
      if (f < 0) {
        f = -f;
      }
      let context = this.$refs.myCanvas.getContext("2d");
      if (this.caozuoType == 2) {
        context.ellipse(a, b, c, d, 0, 0, Math.PI * 2);
        context.strokeStyle = "#FFFFFF";
        context.lineWidth = 3;
        context.stroke();
        let imgdata = context.getImageData(
          0,
          0,
          this.$refs.myCanvas.width,
          this.$refs.myCanvas.height
        );
        this.spliceCanvasDaata();
        this.canvasData.push(imgdata);
        this.canvasIndex++;
      }
      if (this.caozuoType == 3) {
        context.rect(this.beginRec.x, this.beginRec.y, l, f);
        context.strokeStyle = "#FFFFFF";
        context.lineWidth = 3;
        context.stroke();
        let imgdata = context.getImageData(
          0,
          0,
          this.$refs.myCanvas.width,
          this.$refs.myCanvas.height
        );
        this.spliceCanvasDaata();
        this.canvasData.push(imgdata);
        this.canvasIndex++;
      }
      context.save();
    },
    //获取画笔类型
    getType(val) {
      this.caozuoType = val;
    },
    //添加文字
    luruFont() {
      let ctmyCanvas = this.$refs.myCanvas;
      var stringa = document.getElementById("fontInput").value;
      console.log(stringa);
      console.log(stringa.split("/s/g"));
      document.getElementById("fontInput").style =
        "z-index: 2;display:none;border:2px solid groove;position:absolute;";
      var context = ctmyCanvas.getContext("2d");
      let fontStr = "" + this.fontSize + "px bold  宋体";
      context.font = fontStr;
      context.fillStyle = "#FFFFFF";
      let str = document.getElementById("fontInput").value;
      let fontmount = parseInt(this.fontMount);
      for (let i = 0; i < str.length; i += fontmount) {
        context.fillText(
          str.substring(i, i + fontmount),
          this.beginRec.x,
          this.beginRec.y + 15 + (i / fontmount) * (parseInt(this.fontSize) + 2)
        );
      }
      // context.fillText(
      //     document.getElementById("fontInput").value,
      //     this.beginRec.x,
      //     this.beginRec.y + 15
      // );
      context.save();
      let imgdata = context.getImageData(
        0,
        0,
        ctmyCanvas.width,
        ctmyCanvas.height
      );
      this.spliceCanvasDaata();
      this.canvasData.push(imgdata);
      this.canvasIndex++;
      console.log(this.canvasIndex);
      console.log(this.canvasData);
    },
    //点击画布事件
    huoquzuobiao(e) {
      if (this.caozuoType == 1) {
        this.fontX = e.offsetX;
        this.fontY = e.offsetY;
        (this.intputFontX = e.offsetX), (this.intputFontY = e.offsetY);
        document.getElementById("fontInput").style =
          "z-index:11111;border:2px solid groove;position:absolute;left:" +
          (e.offsetX + (1200 - this.canvas.width) / 2) +
          "px;top:" +
          (e.offsetY + 110) +
          "px;height:+" +
          this.fontSize * 3 +
          "px; font-size:" +
          this.fontSize +
          "px;";
        //   document.getElementById("fontInput").style="float-left:"+this.fontX+";float-top:"+this.fontY+";border:2px solid groove;relative:absolute;left:"+this.fontX+";top:"+this.fontY+";opacity:.5"
      }
    },
    //重置画布
    shuaxinhuabu() {
      this.jiaodu = 0;
      var canvas = this.$refs.myCanvas;
      if (canvas.getContext) {
        //获取对应的CanvasRenderingContext2D对象(画笔)
        let ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        //创建新的图片对象
        var img = new Image();
        //指定图片的URL
        //浏览器加载图片完毕后再绘制图片
        img.src = this.imgUrl + "?timeStamp=" + new Date().valueOf();
        img.crossOrigin = "anonymous";
        img.onload = function() {
          //在Canvas画中间布绘制图像
          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(
            img,
            canvas.width / 2 - img.width / 2,
            canvas.height / 2 - img.height / 2
          );
        };
        this.img = img;
        this.canvas = canvas;
      }
    },
    // 文件上传之选择文件并赋值
    getFile(event) {
      this.jianchajieguoPicBean.jcjgPicFile = event.target.files[0];
    },
    // 文件上传
    formCommitPic() {
      let dataform = new FormData();
      dataform.append("jcjgPicFile", this.jianchajieguoPicBean.jcjgPicFile);
      dataform.append("xiangmuId", this.jianchajieguoPicBean.jcjgPicId);
      this.$axios
        .post(
          "http://www.baidu.com",//上传地址
          dataform,
          { "Content-Type": "multipart/form-data" }
        )
        .then(response => {
          if (response.data.code == "000000") {
            alert("修改成功");
            this.dialogFormPic = false;
            this.getJianchabaogao();
            this.jianchajieguoPicBean = {
              jcjgPicFile: "",
              jcjgPicId: ""
            };
          }
        });
    },
    // 修改图片
    updateJianchaPic(val, picID) {
      this.canvasIndex = 0;
      this.canvasData = [];
      this.jcjgPicId = picID;
      document.getElementById("huabuDiv").style = "display:block";
      this.dialogds = true;
      this.huatuPic = true;
      this.imgUrl = this.zhuanhuanwangzhi(val);
      this.shuaxinhuabu();
    }
  }
};
</script>
<style >
</style>


注意

需要解决文件的跨域问题,代码内目前只做了文字、椭圆、方形、图片裁剪和旋转的处理,并且可能存在bug,只是记录一下,有类似需求的同学可以在此基础上做自己的业务功能

示例

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值