You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Canvas居中时如何判断鼠标是否点击到画布内的图形?

解决Canvas图形点击检测问题

这是我的Canvas(蓝色边框)和绿色图形

我的Canvas处于屏幕中央,添加点击事件后调用console.log(e.clientX, e.clientY)得到的是例如530,483这样的屏幕坐标,但我的图形相对于Canvas的坐标是50,50。我该如何判断自己点击的是图形而非Canvas背景区域?

用户提供的代码:

let shapes:any = [];
shapes.push({ x:50, y:50, width: this.qrSize, height: this.qrSize, color:'lightgreen' })

let is_mouse_in_shape = function(x:any, y:any, shape:any){
  let shape_left = shape.x;
  let shape_right = shape.x + shape.width;
  let shape_top = shape.y;
  let shape_bottom = shape.y + shape.height;
  console.log(x,y)        // x = 415, y = 467
  console.log(shape_left, shape_top)         // x = 50, y = 50
  if( x > shape_left && x < shape_right && y > shape_top && y > shape_bottom ){
    return true;
  }
  return false; // 此处始终返回false
}
let mouse_down = function(event:any){
  event.preventDefault();
  startX = parseInt(event.clientX);
  startY = parseInt(event.clientY);
  console.log(event)
  let index = 0;
  for(let shape of shapes){
    if(is_mouse_in_shape(startX, startY, shape)){
      console.log('yes');
      current_shape_index = index;
    } else {
      console.log('no')
    }
    index++;
  }
}
let draw_shapes = function(){
  context.clearRect(0,0, canvas_width, canvas_height);
  for (let shape of shapes){
    context.fillStyle = shape.color;
    context.fillRect(shape.x, shape.y, shape.width, shape.height);
  }
}
draw_shapes();
canvas.onmousedown = mouse_down;

问题分析与修正方案

你的代码存在两处关键问题,直接导致点击检测失效:

  1. 未转换屏幕坐标为Canvas相对坐标:clientX/clientY是相对于浏览器视口的坐标,需要转换成Canvas自身坐标系的坐标才能和图形的本地坐标对比。
  2. y轴判断条件错误:is_mouse_in_shape函数中y > shape_bottom应该改为y < shape_bottom,否则逻辑完全颠倒。

修正后的完整代码

let shapes:any = [];
shapes.push({ x:50, y:50, width: this.qrSize, height: this.qrSize, color:'lightgreen' })

let is_mouse_in_shape = function(x:number, y:number, shape:any){
  const shapeLeft = shape.x;
  const shapeRight = shape.x + shape.width;
  const shapeTop = shape.y;
  const shapeBottom = shape.y + shape.height;
  // 修正y轴判断条件
  return x > shapeLeft && x < shapeRight && y > shapeTop && y < shapeBottom;
}

let mouse_down = function(event:MouseEvent){
  event.preventDefault();
  // 获取Canvas在视口中的位置信息
  const rect = canvas.getBoundingClientRect();
  // 转换为Canvas相对坐标
  const canvasX = event.clientX - rect.left;
  const canvasY = event.clientY - rect.top;
  
  let index = 0;
  for(let shape of shapes){
    if(is_mouse_in_shape(canvasX, canvasY, shape)){
      console.log('yes');
      current_shape_index = index;
    } else {
      console.log('no')
    }
    index++;
  }
}

let draw_shapes = function(){
  context.clearRect(0,0, canvas_width, canvas_height);
  for (let shape of shapes){
    context.fillStyle = shape.color;
    context.fillRect(shape.x, shape.y, shape.width, shape.height);
  }
}

draw_shapes();
canvas.onmousedown = mouse_down;

关键说明

  • 使用canvas.getBoundingClientRect()获取Canvas元素在浏览器视口中的位置(left、top等属性),用鼠标的视口坐标减去这些值,就能得到相对于Canvas左上角的坐标。
  • 修正is_mouse_in_shape中的y轴判断逻辑,确保只有当鼠标y坐标在图形的top和bottom之间时才返回true。

内容的提问来源于stack exchange,提问作者Nawapol R.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:50:28