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

如何为canvas中drawImage绘制的元素绑定onClick点击事件

实现思路说明

你之前的方案不生效的核心原因:Canvas 是位图画布,通过drawImage绘制到画布上的内容只是像素集合,不属于 DOM 元素,你给内存中的Image对象绑定点击事件,和画布上渲染的图案没有关联,自然不会触发。

可行的实现方案是手动做点击碰撞检测,具体步骤如下:

  • 存储所有绘制的GPS图标的位置、尺寸、关联属性
  • 给Canvas元素本身绑定点击事件,计算点击位置相对于Canvas的内部坐标
  • 遍历存储的图标列表,判断点击坐标是否落在某个图标的范围内,命中则执行对应的逻辑
修改后的完整代码

JS代码

let last_spawn_id = 0;
// 存储所有标记的信息
const markers = [];

function getPictureCoords(x, y, z) {
  return {x: 485 + x/11.6804138437 , y: 705 - y/11.6804138437}
}

const ctx = document.getElementById('map').getContext('2d')
const mapCanvas = document.getElementById('map')

function drawPlayerMarker(x, y, z, name) {
    last_spawn_id += 1;
    const newCoords = getPictureCoords(x, y, z)
    const renderX = newCoords.x
    const renderY = newCoords.y
    
    const base_image = new Image();
    base_image.src = 'https://i.imgur.com/I1KVjGJ.png';
    const markerId = `item_${last_spawn_id}`;
    
    base_image.onload = function(){
        // 这里可以手动指定图标绘制的宽高,比如24*24,不指定就用原图尺寸
        const iconWidth = base_image.naturalWidth;
        const iconHeight = base_image.naturalHeight;
        ctx.drawImage(base_image, renderX, renderY, iconWidth, iconHeight);
        // 把标记信息存入数组
        markers.push({
            id: markerId,
            name: name,
            x: renderX,
            y: renderY,
            width: iconWidth,
            height: iconHeight
        })
    }
}

// 给canvas绑定点击事件
mapCanvas.addEventListener('click', (e) => {
    // 计算点击位置相对于canvas的内部坐标
    const rect = mapCanvas.getBoundingClientRect();
    const clickX = e.clientX - rect.left;
    const clickY = e.clientY - rect.top;
    
    // 遍历所有标记做碰撞检测
    for(let marker of markers) {
        if(
            clickX >= marker.x && 
            clickX <= marker.x + marker.width &&
            clickY >= marker.y &&
            clickY <= marker.y + marker.height
        ) {
            // 命中目标,打印日志
            console.log(`点击了GPS图标,id:${marker.id},名称:${marker.name}`)
            // 匹配到就跳出循环,不需要继续检测
            break;
        }
    }
})

drawPlayerMarker(0, 0, 0, "Re")

CSS代码

body {
    zoom: 90%;
}
html, body {
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;
}

HTML代码(修复了canvas标签未闭合的问题)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<body>
<img src='https://i.imgur.com/qpZ4eWh.jpg' style="position: absolute">
<canvas height='1080' width='1080' id='map' style='height: 1080px; width: 1080px; position: absolute; z-index: 9999'></canvas>
</body>
补充说明

如果你的GPS图标是不规则形状,需要更精准的点击判定,可以在碰撞检测时额外判断点击位置对应的Canvas像素透明度,非透明则判定为命中,普通场景下矩形检测已经可以满足需求。

内容的提问来源于stack exchange,提问作者diversecheck123

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 13:06:03