vue 使用canvas做选取并获取相对于图片的比例坐标点

图片在canvas中自适应大小并居中。
通常图片大小与canvas的大小是不同的,分为以下几种情况

图片高或宽,超过canvas高或宽
图片高、宽,都超过canvas高宽;
图片高、宽都小于canvas高、宽

问题的本质其实是动态计算图片大小,并在canvas适合的位置画出图片,并能获取选取的坐标点

<template>
  <div class="app-container">
    <el-row :gutter="20">
      <el-col :span="6">1</el-col>
      <el-col :span="18" class="wrap" ref="wrap">
        <div id="divHeight">
          <canvas id="canvaxbox" ref="canvaxbox"></canvas>
          <!--用来和鼠标进行交互操作的canvas-->
          <canvas id="canvas" ref="canvas"> </canvas>
          <!--存储已生成的点线,避免被清空-->
          <canvas id="canvasSave" ref="canvasSave"></canvas>
        </div>
        <div id="shouPointArr">
          <input
            id="deleteCanvas"
            ref="deleteCanvas"
            type="button"
            value="清空选区"
          />
          <input
            id="ratioPointArr"
            ref="ratioPointArr"
            type="text"
            value=""
            readonly="readonly"
          />
        </div>
      </el-col>
    </el-row>
  </div>
</template>
<script>

export default {
  name: "identifyArea",
  data() {
    return {
      canvasHeight:""
    };
  },
  mounted() {
    this.init();
    console.log("this.canvasHeight--")
    console.log(this.canvasHeight)
    
  },
  methods: {
    init() {
      var c = document.getElementById("canvaxbox");
      var canvas = c.getContext("2d");
      var img = new Image();
      img.onload = imgfn; //图片加载完在执行
      img.src =
        "https://open.ys7.com/api/lapp/mq/downloadurl?appKey=0eb63461646743bfbff8bfb642088ff3&fileKey=ISAPI_FILES/E47730522_1/20210407135016307-E47730522-1-10000$encrypt=2,2021-04-07T13:50:15,c93025e41acb6f2d1bb1567fde4b5c9d";
      console.log("img");
      console.log(img);
      // img.src = [[${url}]];
      c.width = 0;
      c.height = 0;
      var w = 0;
      var h = 0;
      var wrapWidth = this.$refs.wrap.$el.clientWidth;
      function imgfn() {
        var imgWidth = img.width;
        var imgHeight = img.height;
        var ratio = imgHeight / imgWidth;
        var wrapHeight = parseInt(wrapWidth * ratio);
        var outHeight = document.getElementById("divHeight");
        outHeight.style.height = wrapHeight + 'px'
        console.log("this.canvasHeight")
        console.log(this.canvasHeight)
        c.width = wrapWidth;
        c.height = wrapHeight;
        w = wrapWidth;
        h = wrapHeight;
        var iw = img.width;
        var ih = img.height;
        var local = calculate(iw, ih);
        canvas.fillStyle = "white";
        canvas.fill();
        canvas.drawImage(img, local.px, local.py, local.pw, local.ph);

        //绘制多边形
        var can = document.getElementById("canvas");
        var ctx = can.getContext("2d");
        var canSave = document.getElementById("canvasSave");
        var ctxSave = canSave.getContext("2d");

        var pointX, pointY;
        var pointArr = []; //存放坐标的数组

        //设置和图片长宽 一致
        can.width = wrapWidth;
        can.height = wrapHeight;
        canSave.width = wrapWidth;
        canSave.height = wrapHeight;

        ctx.strokeStyle = "rgba(102,168,255,1)"; //线条颜色
        ctx.lineWidth = 4; //线条粗细
        ctxSave.strokeStyle = "rgba(102,168,255,1)"; //线条颜色
        ctxSave.lineWidth = 4; //线条粗细

        var oIndex = -1; //判断鼠标是否移动到起始点处,-1为否,1为是

        /*点击画点*/
        can.addEventListener("click", function (e) {
          if (e.offsetX || e.layerX) {
            pointX = e.offsetX == undefined ? e.layerX : e.offsetX;
            pointY = e.offsetY == undefined ? e.layerY : e.offsetY;
            var piX, piY;
            if (oIndex > 0 && pointArr.length > 0) {
              piX = pointArr[0].x;
              piY = pointArr[0].y;
              //画点
              makearc(
                ctx,
                piX,
                piY,
                GetRandomNum(2, 2),
                0,
                180,
                "rgba(102,168,255,1)"
              );
              pointArr.push({ x: piX, y: piY });
              canvasSave(pointArr); //保存点线同步到另一个canvas
              saveCanvas(); //生成画布
            } else {
              piX = pointX;
              piY = pointY;
              makearc(
                ctx,
                piX,
                piY,
                GetRandomNum(2, 2),
                0,
                180,
                "rgba(102,168,255,1)"
              );
              pointArr.push({ x: piX, y: piY });
              canvasSave(pointArr); //保存点线同步到另一个canvas
            }
          }
        });
        // 计算出图片画在canvas中的四个参数
        function calculate(pw, ph) {
          var px = 0;
          var py = 0;
          if (pw < w && ph < h) {
            px = 0.5 * w - 0.5 * pw;
            py = 0.5 * h - 0.5 * ph;
          } else if (ph / pw > h / w) {
            var uu = ph;
            ph = h;
            pw = (pw * h) / uu;
            px = 0.5 * w - 0.5 * pw;
          } else {
            var uu = pw;
            pw = w;
            ph = (ph * pw) / uu;
            py = 0.5 * h - 0.5 * ph;
          }
          return { px, py, pw, ph };
        }

        /*  */
        can.addEventListener("mousemove", function (e) {
          if (e.offsetX || e.layerX) {
            pointX = e.offsetX == undefined ? e.layerX : e.offsetX;
            pointY = e.offsetY == undefined ? e.layerY : e.offsetY;
            var piX, piY;
            /*清空画布*/
            ctx.clearRect(0, 0, can.width, can.height);
            /*鼠标下跟随的圆点*/
            makearc(
              ctx,
              pointX,
              pointY,
              GetRandomNum(4, 4),
              0,
              180,
              "rgba(255,109,0,1)"
            );

            if (pointArr.length > 0) {
              if (
                pointX > pointArr[0].x - 15 &&
                pointX < pointArr[0].x + 15 &&
                pointY > pointArr[0].y - 15 &&
                pointY < pointArr[0].y + 15
              ) {
                if (pointArr.length > 1) {
                  piX = pointArr[0].x;
                  piY = pointArr[0].y;
                  ctx.clearRect(0, 0, can.width, can.height);
                  makearc(
                    ctx,
                    piX,
                    piY,
                    GetRandomNum(4, 4),
                    0,
                    180,
                    "rgba(102,168,255,1)"
                  );
                  oIndex = 1;
                }
              } else {
                piX = pointX;
                piY = pointY;
                oIndex = -1;
              }
              /*开始绘制*/
              ctx.beginPath();
              ctx.moveTo(pointArr[0].x, pointArr[0].y);
              if (pointArr.length > 1) {
                for (var i = 1; i < pointArr.length; i++) {
                  ctx.lineTo(pointArr[i].x, pointArr[i].y);
                }
              }
              ctx.lineTo(piX, piY);
              ctx.fillStyle = "rgba(161,195,255,1)"; //填充颜色
              ctx.fill(); //填充
              ctx.stroke(); //绘制
            }
          }
        });

        // 存储已生成的点线
        function canvasSave(pointArr) {
          ctxSave.clearRect(0, 0, ctxSave.width, ctxSave.height);
          ctxSave.beginPath();
          if (pointArr.length > 1) {
            ctxSave.moveTo(pointArr[0].x, pointArr[0].y);
            for (var i = 1; i < pointArr.length; i++) {
              ctxSave.lineTo(pointArr[i].x, pointArr[i].y);
              ctxSave.fillStyle = "rgba(161,195,255,1)"; //填充颜色
              //ctxSave.fill();
              ctxSave.stroke(); //绘制
            }
            ctxSave.closePath();
          }
        }

        /*生成画布 结束绘画*/
        function saveCanvas() {
          ctx.clearRect(0, 0, can.width, can.height);
          ctxSave.closePath(); //结束路径状态,结束当前路径,如果是一个未封闭的图形,会自动将首尾相连封闭起来
          ctxSave.fill(); //填充
          ctxSave.stroke(); //绘制
          //计算坐标点
          calPoint(pointArr);

          pointArr = [];
        }

        /*清空选区*/
        document
          .getElementById("deleteCanvas")
          .addEventListener("click", function (e) {
            ctx.clearRect(0, 0, can.width, can.height);
            ctxSave.clearRect(0, 0, canSave.width, canSave.height);
            pointArr = [];
            document.getElementById("ratioPointArr").value = "";
          });

        /*验证canvas画布是否为空函数*/
        function isCanvasBlank(canvas) {
          var blank = document.createElement("canvas"); //创建一个空canvas对象
          blank.width = canvas.width;
          blank.height = canvas.height;
          return canvas.toDataURL() == blank.toDataURL(); //为空 返回true
        }

        /*canvas生成圆点*/
        function GetRandomNum(Min, Max) {
          var Range = Max - Min;
          var Rand = Math.random();
          return Min + Math.round(Rand * Range);
        }

        function makearc(ctx, x, y, r, s, e, color) {
          ctx.clearRect(0, 0, 199, 202); //清空画布
          ctx.beginPath();
          ctx.fillStyle = color;
          ctx.arc(x, y, r, s, e);
          ctx.fill();
        }

        /*计算生成坐标比例*/
        function calPoint(pointArr) {
          let ratioPointArr = [];

          //循环计算坐标点
          for (let i = 0; i < pointArr.length - 1; i++) {
            let ratioPoint = [];
            //判断坐标点为负
            if (pointArr[i].x < 0) {
              pointArr[i].x = 0;
            }

            if (pointArr[i].y < 0) {
              pointArr[i].y = 0;
            }

            ratioPoint.push(pointArr[i].x / img.width);
            ratioPoint.push(pointArr[i].y / img.height);
            ratioPointArr.push(ratioPoint);
          }
          console.log(ratioPointArr);
          document.getElementById("ratioPointArr").value = ratioPointArr;
        }
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.wrap {
  position: relative;
  padding-left: 0;
  padding-right: 0;
}
#shouPointArr {
  width: 100px;
  margin-left: 200px;
  // margin-top: 520px;
}
canvas {
  // border: 1px solid #333;
  display: block;
}

#canvaxbox {
  position: absolute;
  left: 0;
  top: 0;
}

#canvas {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1;
  cursor: crosshair;
}

#canvasSave {
  position: absolute;
  left: 0;
  top: 0;
}
</style>
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值