Canvas加载图片并可缩放并可点击绘制点及图片像素点坐标

10/22/2024 Canvas

# 前言

与人员定位系统对接时,有个获取图片指定位置的像素图标(以图片的左上角为(0,0)点)。

# 一、原生js方式

用原生的点击事件和event中的layerX和layerY,发现可行。

<body>
  <img src="./0.jpg" />
  <script>
    document.addEventListener('click',(event)=>{
      console.log(event.layerX,event.layerY);
    })
  </script>
</body>
1
2
3
4
5
6
7
8

但是有几个不便:

  • 1.图片很大,会出现上下、左右的滚动条;
  • 2.缩放只能靠缩放浏览器的缩放来控制;
  • 3.后续绘制线、面貌似没有可行度。

# 二、用canvas方式

有一个想法,就是将canvas当作地图,可以缩放、平移、点击、绘制;图片是就是地图,坐标原点是图片的左上角。 查找了这方面的例子,有个相近的,稍微改改就能用,下面是修改后的代码:

<body>
  <canvas id="canvas" width="800" height="800"></canvas>
  <script type="text/javascript" src="main.js"></script>
</body>
1
2
3
4

main.js

var canvas, cxt;
var img,//图片对象
  imgIsLoaded,//图片是否加载完成;
  imgX = 0, // 在canvas上放置图片x坐标;
  imgY = 0, // 在canvas上放置图片y坐标;
  imgScale = 1;

canvas = document.getElementById('canvas');
cxt = canvas.getContext('2d');
loadImg();

function loadImg() {
  img = new Image();
  img.onload = function () {
    imgIsLoaded = true;
    drawImage();
  }
  img.src = "0.jpg";
}

function drawImage() {
  cxt.clearRect(0, 0, canvas.width, canvas.height);
  // drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
  // img  规定要使用的图像、画布或视频。
  // sx 可选。开始剪切的 x 坐标位置。
  // sy 可选。开始剪切的 y 坐标位置。
  // swidth 可选。被剪切图像的宽度。
  // sheight  可选。被剪切图像的高度。
  // x  在画布上放置图像的 x 坐标位置。
  // y  在画布上放置图像的 y 坐标位置。
  // width  可选。要使用的图像的宽度。(伸展或缩小图像)
  // height 可选。要使用的图像的高度。(伸展或缩小图像)
  cxt.drawImage(img, 0, 0, img.width, img.height, imgX, imgY, img.width * imgScale, img.height * imgScale);
}

canvas.onmousedown = function (event) {
  var pos = windowToCanvas(canvas, event.clientX, event.clientY); // 当前canvas坐标
  canvas.onmousemove = function (event) {
    canvas.onclick = null;
    canvas.style.cursor = "move";
    var pos1 = windowToCanvas(canvas, event.clientX, event.clientY);
    var x = pos1.x - pos.x; // canvas坐标中的鼠标偏移量x
    var y = pos1.y - pos.y; // canvas坐标中的鼠标偏移量y
    pos = pos1; // 现在canvas坐标
    imgX += x;
    imgY += y;
    drawImage();
  }

  canvas.onmouseup = function () {
    canvas.onmousemove = null;
    canvas.onmouseup = null;
    canvas.style.cursor = "default";
  }

  canvas.onclick = getImagePointPixel;
}

canvas.onmousewheel = canvas.onwheel = function (event) {
  var pos = windowToCanvas(canvas, event.clientX, event.clientY);
  event.wheelDelta = event.wheelDelta ? event.wheelDelta : (event.deltaY * (-40));
  if (event.wheelDelta > 0) {
    imgScale *= 2;
    imgX = imgX * 2 - pos.x;
    imgY = imgY * 2 - pos.y;
  } else {
    imgScale /= 2;
    imgX = imgX * 0.5 + pos.x * 0.5;
    imgY = imgY * 0.5 + pos.y * 0.5;
  }
  drawImage();
}
  
// 屏幕坐标转换为canvas坐标
function windowToCanvas(canvas, x, y) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: x - rect.left - (rect.width - canvas.width) / 2,
    y: y - rect.top - (rect.height - canvas.height) / 2
  };
}
  
// 鼠标点击事件处理函数
canvas.onclick = getImagePointPixel;

function getImagePointPixel(e) {
  var rect = canvas.getBoundingClientRect();
  var x = e.clientX - rect.left - imgX;
  var y = e.clientY - rect.top - imgY;
  x = Math.round(x / imgScale);
  y = Math.round(y / imgScale);
  // 鼠标在图片上的像素坐标
  console.log(`{ "x":${x}, "y":${y} }`)
  
  cxt.beginPath();
  cxt.fillStyle = 'red';
  cxt.arc(e.clientX, e.clientY, 5, 0, 2 * Math.PI); // 绘制一个圆形,作为点
  cxt.fill();
}
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
Last Updated: 2/15/2025, 2:22:53 PM