如何为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
相关产品推荐
相关产品推荐

