当前位置:   article > 正文

vue 图片画框获取坐标_vue3 el-img 获取图像区域坐标

vue3 el-img 获取图像区域坐标

创建draw.js文件

/**
 * 画布中绘制矩形
 * 参数: cav-画布对象  list-矩形数组 i-选中矩形下标
 **/

/* 操作执行方法分发 */
export function draw(cav, list, i) {
  // 画布初始化
  let ctx = cav.getContext('2d');
  ctx.strokeStyle = 'blue';
  ctx.lineWidth = 2;

  // 变量初始化
  let sX = 0; // 鼠标X坐标
  let sY = 0; // 鼠标Y坐标

  /*
   *鼠标移动进行第一层判断, 区分情况: 无矩形, 已有矩形无选中, 已有选中矩形
   */
  cav.onmousemove = function (em) {
    sX = em.offsetX;
    sY = em.offsetY;
    let iem = undefined; // 鼠标移动时临时存储当前鼠标所在矩形的下标

    if (list.length === 0) { // **** 无矩形 ****
      // 绘制新矩形
      newDraw(cav, ctx, list);
    } else if (i === undefined) { // **** 已有矩形无选中 ****
      // 判断鼠标位置
      list.forEach(function (value, index, array) {
        if (value.w > 0 && value.h > 0 && sX > value.x && sX < value.x + value.w && sY > value.y && sY < value.y + value.h) {
          // 鼠标在右下方向生成的矩形中
          iem = index;
          judgeDraw(cav, ctx, list, iem);
        }
        if (value.w < 0 && value.h > 0 && sX < value.x && sX > value.x + value.w && sY > value.y && sY < value.y + value.h) {
          // 鼠标在左下方向生成的矩形中
          iem = index;
          judgeDraw(cav, ctx, list, iem);
        }
        if (value.w > 0 && value.h < 0 && sX > value.x && sX < value.x + value.w && sY < value.y && sY > value.y + value.h) {
          // 鼠标在右上方向生成的矩形中
          iem = index;
          judgeDraw(cav, ctx, list, iem);
        }
        if (value.w < 0 && value.h < 0 && sX < value.x && sX > value.x + value.w && sY < value.y && sY > value.y + value.h) {
          // 鼠标在左上方向生成的矩形中
          iem = index;
          judgeDraw(cav, ctx, list, iem);
        }
        if (iem === undefined) {
          // 鼠标不在矩形中
          newDraw(cav, ctx, list);
        }
      })
    } else { // **** 已有选中矩形 ****
      // 判断鼠标位置
      for (let index = 0; index < list.length; index++) {
        let value = list[index];
        if (sX < value.x + 5 && sX > value.x - 5 && sY < value.y + 5 && sY > value.y - 5) {
          // ***  鼠标在起点角  ***
          if (index === i) {
            changeDraw(cav, ctx, list, i, 1);
            break;
          }
        } else if (sX < value.x + value.w + 5 && sX > value.x + value.w - 5 && sY < value.y + 5 && sY > value.y - 5) {
          // ***  鼠标在起点横向角  ***
          if (index === i) {
            changeDraw(cav, ctx, list, i, 2);
            break;
          }

        } else if (sX < value.x + 5 && sX > value.x - 5 && sY < value.y + value.h + 5 && sY > value.y + value.h - 5) {
          // ***  鼠标在起点纵向角  ***
          if (index === i) {
            changeDraw(cav, ctx, list, i, 3);
            break;
          }

        } else if (sX < value.x + value.w + 5 && sX > value.x + value.w - 5 && sY < value.y + value.h + 5 && sY > value.y + value.h - 5) {
          // ***  鼠标在终点角  ***
          if (index === i) {
            changeDraw(cav, ctx, list, i, 4);
            break;
          }

        } else if (value.w > 0 && value.h > 0 && sX > value.x && sX < value.x + value.w && sY > value.y && sY < value.y + value.h) {
          // ***  鼠标在右下方向生成的矩形中  ***
          iem = index
          judgeDraw(cav, ctx, list, index);
          break;

        } else if (value.w < 0 && value.h > 0 && sX < value.x && sX > value.x + value.w && sY > value.y && sY < value.y + value.h) {
          // ***  鼠标在左下方向生成的矩形中  ***
          iem = index
          judgeDraw(cav, ctx, list, index);
          break;

        } else if (value.w > 0 && value.h < 0 && sX > value.x && sX < value.x + value.w && sY < value.y && sY > value.y + value.h) {
          // ***  鼠标在右上方向生成的矩形中  ***
          iem = index
          judgeDraw(cav, ctx, list, index);
          break;

        } else if (value.w < 0 && value.h < 0 && sX < value.x && sX > value.x + value.w && sY < value.y && sY > value.y + value.h) {
          // ***  鼠标在左上方向生成的矩形中  ***
          iem = index
          judgeDraw(cav, ctx, list, index);
          break;

        } else {
          if (iem === undefined) {
            // *** 鼠标不在矩形中 ***
            newDraw(cav, ctx, list);
          }
        }
      }
    }

    /* 鼠标移出画布区域时保存选中矩形下标(如有) */
    cav.onmouseout = function (eo) {
      if (i !== undefined) {
        // 初始化
        draw(cav, list, i);
      }
    };
  }
};

/* 编辑矩形四个角 */
function changeDraw(cav, ctx, list, i, site) {
  cav.style.cursor = 'pointer'

  // site: 操作矩形角的位置, 1-起点 2-起点横向 3-起点纵向 4-终点
  let mark = list[i];

  /* 按下鼠标左键 */
  cav.onmousedown = function (ed) {
    // 保存鼠标落下位置的X, Y坐标, firefox中鼠标移动后ed.offsetX ed.offsetY会变成 0, 需要使用临时参数存储起来
    let sX = ed.offsetX; // 起点X坐标
    let sY = ed.offsetY; // 起点Y坐标

    /* 移动鼠标 */
    cav.onmousemove = function (em) {
      // 计算绘制数据
      let iframe = {}
      switch (site) {
        case 1:
          iframe = {
            x: em.offsetX,
            y: em.offsetY,
            w: mark.w - (em.offsetX - sX),
            h: mark.h - (em.offsetY - sY)
          }
          break;
        case 2:
          iframe = {
            x: mark.x,
            y: mark.y + (em.offsetY - sY),
            w: mark.w + (em.offsetX - sX),
            h: mark.h - (em.offsetY - sY)
          }
          break;
        case 3:
          iframe = {
            x: mark.x + (em.offsetX - sX),
            y: mark.y,
            w: mark.w - (em.offsetX - sX),
            h: mark.h + (em.offsetY - sY)
          }
          break;
        case 4:
          iframe = {
            x: mark.x,
            y: mark.y,
            w: mark.w + (em.offsetX - sX),
            h: mark.h + (em.offsetY - sY)
          }
          break;
      }
      list.splice(i, 1, iframe);

      // 重新绘制
      reDraw(cav, ctx, list, i);
    }

    /* 鼠标离开矩形区 */
    cav.onmouseout = function (eo) {
      // 重新绘制
      reDraw(cav, ctx, list);
      // 初始化
      draw(cav, list)
    };

    /* 监听键盘, 点击后可以控制删除, 由于移动矩形事件已经监听了onmousemove, 所以在移动矩形方法中仍有一次调用 */
    delDraw(cav, ctx, list, i);
  }

};

/* 绘制新矩形 */
function newDraw(cav, ctx, list) {
  cav.style.cursor = 'crosshair'
  // 初始化变量
  let start = false; // 画框状态, false时不执行画框操作
  let sX = 0; // 起点X坐标
  let sY = 0; // 起点Y坐标

  /* 按下鼠标左键 */
  cav.onmousedown = function (ed) {
    /* 使用变量 */
    start = true;
    sX = ed.offsetX;
    sY = ed.offsetY;

    /* 重置按键监听, 防止选中取消后仍可删除 */
    delDraw(cav, ctx, list, null)

    /* 鼠标移动 */
    cav.onmousemove = function (em) {
      if (start) {
        // 重新绘制
        reDraw(cav, ctx, list);
        // 设置边框为虚线
        ctx.beginPath();
        ctx.setLineDash([8, 4]);
        ctx.rect(sX, sY, em.offsetX - sX, em.offsetY - sY);
        ctx.stroke();
      }
    }

    /* 鼠标抬起 */
    cav.onmouseup = function (eu) {
      if (start && Math.abs(eu.offsetX - sX) > 10 && Math.abs(eu.offsetY - sY) > 10) {
        // 改变矩形数组
        let frame = {
          x: sX, y: sY, w: eu.offsetX - sX, h: eu.offsetY - sY
        };
        list.push(frame);
        // 重新绘制
        reDraw(cav, ctx, list);
        // 改变画框状态
        start = false
        // 初始化
        draw(cav, list)
      } else {
        // 重新绘制
        reDraw(cav, ctx, list);
        // 改变画框状态
        start = false
        // 初始化
        draw(cav, list)
      }
    };

    /* 鼠标离开矩形区 */
    cav.onmouseout = function (eo) {
      if (start && Math.abs(eo.offsetX - sX) > 10 && Math.abs(eo.offsetY - sY) > 10) {
        // 改变矩形数组
        let frame = {
          x: sX, y: sY, w: eo.offsetX - sX, h: eo.offsetY - sY
        };
        list.push(frame);
        // 重新绘制
        reDraw(cav, ctx, list);
        // 改变画框状态
        start = false;
        // 初始化
        draw(cav, list)
      } else {
        // 重新绘制
        reDraw(cav, ctx, list);
        // 改变画框状态
        start = false
        // 初始化
        draw(cav, list)
      }
    };
  }
};

/* 选中矩形, 重绘矩形, 并分发后续事件 */
function judgeDraw(cav, ctx, list, iem) {
  cav.style.cursor = 'default'
  // 初始化变量
  let sX = 0; // 起点X坐标
  let sY = 0; // 起点Y坐标

  /* 按下鼠标左键 */
  cav.onmousedown = function (ed) {
    sX = ed.offsetX;
    sY = ed.offsetY;

    // 更改选中状态, 重绘矩形
    reDraw(cav, ctx, list, iem);

    /* 当仅点击选中矩形便抬起鼠标后, 重新初始化画布 */
    cav.onmouseup = function () {
      // 重绘矩形
      reDraw(cav, ctx, list, iem);

      // 初始化
      draw(cav, list, iem);
    };

    /* 按住拖动鼠标, 移动选中矩形*/
    moveDraw(cav, ctx, list, iem, sX, sY);

    /* 监听键盘, 点击后可以控制删除, 由于移动矩形事件已经监听了onmousemove, 所以在移动矩形方法中仍有一次调用 */
    delDraw(cav, ctx, list, iem);
  }
};

/* 移动矩形 */
function moveDraw(cav, ctx, list, i, sX, sY) {
  let mark = list[i]
  cav.onmousemove = function (em) {
    let iframe = {
      x: mark.x + (em.offsetX - sX),
      y: mark.y + (em.offsetY - sY),
      w: mark.w,
      h: mark.h
    }
    list.splice(i, 1, iframe);
    /* 监听键盘, 使矩形在移动后仍可删除, 在点击未移动过的矩形时仍有一次监听 */
    delDraw(cav, ctx, list, i);
    // 重新绘制
    reDraw(cav, ctx, list, i);
  }

  cav.onmouseup = function () {
    // 重绘矩形
    reDraw(cav, ctx, list, i);

    // 初始化
    draw(cav, list, i);
  };
};

/* 删除矩形 */
function delDraw(cav, ctx, list, i) {
  /* 按键事件 */
  if (i === null) {
    // i为null时阻止按键监听事件冒泡
    cav.onkeydown = function (k) {
      return false;
    }
  } else {
    // 监听按键事件
    cav.onkeydown = function (k) {
      let key = k.keyCode || k.which;
      if (key == 8 && i !== null) {
        if (list.length >= 1) {
          // 删除数组元素
          list.splice(i, 1);
          // 重绘矩形
          reDraw(cav, ctx, list);
        } else {
          /* 矩形数组长度为0, 已将矩形框全部删除 */
          ctx.clearRect(0, 0, cav.width, cav.height);
        }
        // 重置监听状态, 防止删除完毕后, 按键监听不消失
        delDraw(cav, ctx, list, null)
        // 重绘矩形
        reDraw(cav, ctx, list);
        // 初始化
        draw(cav, list);
      }
    }
  }
};

/* 重绘所有矩形 */
function reDraw(cav, ctx, list, i) {
  ctx.setLineDash([8, 0]); // 设置边框为实线
  ctx.clearRect(0, 0, cav.width, cav.height);
  // 绘制未选中部分
  list.forEach(function (value, index, array) {
    if (i === undefined || index != i) {
      ctx.beginPath();
      ctx.strokeStyle = 'blue';
      ctx.rect(value.x, value.y, value.w, value.h);
      ctx.stroke();
    }
  });
  // 绘制已选中部分
  list.forEach(function (value, index, array) {
    if (index === i) {
      /* 绘制方框 */
      ctx.beginPath();
      ctx.strokeStyle = 'red';
      ctx.rect(value.x, value.y, value.w, value.h);
      ctx.fillStyle = 'RGBA(102,102,102,0.2)'
      ctx.fillRect(value.x, value.y, value.w, value.h);
      ctx.stroke();
      // 绘制四个角的圆圈
      ctx.beginPath();
      ctx.strokeStyle = 'red';
      ctx.arc(value.x, value.y, 4, 0, Math.PI * 2)
      ctx.fillStyle = "red";
      ctx.fill();// 画起点实心圆
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(value.x, value.y + value.h, 4, 0, Math.PI * 2);
      ctx.fillStyle = "red";
      ctx.fill();// 画起点纵向实心圆
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(value.x + value.w, value.y + value.h, 4, 0, Math.PI * 2);
      ctx.fillStyle = "red";
      ctx.fill();// 画起点横向实心圆
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(value.x + value.w, value.y, 4, 0, Math.PI * 2);
      ctx.fillStyle = "red";
      ctx.fill();// 画终点实心圆
      ctx.stroke();
    }
  })
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421

vue文件中引入draw方法

  import {draw} from "../../utils/draw";
  • 1

编写dom

    <el-dialog
      title="图片画图"
      :visible.sync="imageDialog"
      width="1240px">
      <div class="imgcontent"  v-loading="loadingImg">
        <el-image style="width:1200px;height: 675px" :src="taskTypeImage"></el-image>
        <canvas ref="markCanvas"></canvas>
      </div>
      <span slot="footer" class="dialog-footer">
                    <el-button @click="imageDialog = false">取 消</el-button>
                   <el-button type="primary" @click="confirmImg">确 定</el-button>
              </span>
    </el-dialog>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

初始化加载方法

initCanvas() {
        let that = this
        this.$nextTick(() => {
          // 初始化canvas宽高
          let cav = this.$refs.markCanvas;
          cav.width = 1200;
          cav.height = 675;
          let ctx = cav.getContext('2d');
          ctx.strokeStyle = 'red'
          cav.style.cursor = 'crosshair'

          // 计算使用变量
          let list = this.markList; // 画框数据集合, 用于服务端返回的数据显示和绘制的矩形保存
          // 若服务端保存的为百分比则此处需计算实际座标, 直接使用实际座标可省略
          list.forEach(function (value, index, array) {
            let newValue = {
              x: value.x * cav.width,
              y: value.y * cav.height,
              w: value.w * cav.width,
              h: value.h * cav.height,
            }
            list.splice(index, 1, newValue)
          })

          // 若list长度不为0, 则显示已标记框
          if (list.length !== 0) {
            list.forEach(function (value, index, array) {
              // 遍历绘制所有标记框
              ctx.rect(value.x, value.y, value.w, value.h);
              ctx.stroke();
            });
          }

          // 调用封装的绘制方法
          draw(cav,list);

          // 备注: js中对象操作指向的是对象的物理地址, 获取绘制完矩形的结果数组直接取用或处理this.markList即可
        })
      },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

借鉴地址

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/109931
推荐阅读
相关标签
  

闽ICP备14008679号