如何在Canvas上放大图片并绘制矩形?坐标与像素问题咨询
关于Canvas放大图片后获取原始像素坐标的解决方案
嘿,这个问题问到点子上了!直接说结论:放大图片后不能直接用原来的方式获取原始图片像素坐标,得做一步坐标转换才行。咱们结合你的代码来一步步说:
当前代码的现状
你现在的drawImageActualSize函数是把Canvas的尺寸设成和图片的自然尺寸完全一致,这时候鼠标在Canvas上的坐标和原始图片的像素坐标是一一对应的,所以没问题。但一旦你放大了图片(比如把Canvas显示尺寸调大,或者用drawImage的缩放参数绘制),鼠标获取的坐标就变成了放大后的显示坐标,和原始像素就不匹配了。
解决思路:计算缩放比例,转换坐标
核心就是先算出图片的缩放比例,再把鼠标获取的显示坐标除以这个比例,得到原始图片的像素坐标。
1. 调整图片绘制逻辑,记录缩放比例
假设你要把图片放大到指定倍数(比如1.5倍),修改你的绘制函数,同时保存缩放比例:
// 新增缩放倍数变量,可根据需求动态调整 scope.imageScale = 1.5; function drawScaledImage() { const naturalWidth = scope.image.naturalWidth; const naturalHeight = scope.image.naturalHeight; // 设置Canvas绘图缓冲区尺寸为缩放后的大小 scope.canvas.width = naturalWidth * scope.imageScale; scope.canvas.height = naturalHeight * scope.imageScale + scope.heightOfHeader.height; $('#canvas').css("top", `-${scope.heightOfHeader.height}`); // 绘制缩放后的图片 scope.canvasForImageCtx.drawImage( scope.image, 0, 0, naturalWidth, naturalHeight, // 原始图片的区域 0, 0, naturalWidth * scope.imageScale, naturalHeight * scope.imageScale // 缩放后的绘制区域 ); // 保存缩放比例,方便后续坐标转换 scope.scaleX = scope.imageScale; scope.scaleY = scope.imageScale; }
如果是不等比缩放(比如宽和高缩放比例不同),就分别计算scaleX和scaleY:
scope.displayWidth = 800; // 你想要的Canvas显示宽度 scope.displayHeight = 600; // 你想要的Canvas显示高度 scope.scaleX = scope.displayWidth / scope.image.naturalWidth; scope.scaleY = scope.displayHeight / scope.image.naturalHeight;
2. 修正鼠标坐标,转换为原始像素坐标
在你处理鼠标事件(比如按下、移动)的时候,把获取到的显示坐标转换成原始图片的像素坐标:
// 举个鼠标移动事件的例子 $('#canvas').mousemove(function(e) { // 获取鼠标在Canvas上的相对显示坐标 scope.mousex = e.pageX - scope.canvasx; scope.mousey = e.pageY - scope.canvasy; // 转换为原始图片的像素坐标 const originalPixelX = scope.mousex / scope.scaleX; const originalPixelY = scope.mousey / scope.scaleY; // 之后就用originalPixelX和originalPixelY来记录矩形的左上角坐标 // 比如绘制矩形或者保存到boundingBoxObject里 });
3. 注意事项
- 区分Canvas的
width/height属性和CSS的width/height:前者是绘图缓冲区的实际像素尺寸,后者是显示尺寸。我们要保证width/height属性是缩放后的像素值,这样绘图才不会模糊,坐标计算也准确。 - 如果涉及到滚动或者Canvas的定位偏移,要确保
canvasx和canvasy的计算是正确的,避免坐标偏移。
总结
只要你通过缩放比例把鼠标获取的显示坐标转换成原始图片的像素坐标,就可以和没放大时一样,正确获取到原始图片的像素位置,然后正常发送给REST API啦。
内容的提问来源于stack exchange,提问作者TrickOrTreat




