画布中的真实鼠标位置

2023-11-25

我正在尝试用鼠标在 HTML5 画布上进行绘制,但似乎效果良好的唯一方法是,如果我出于某种原因更改画布位置,则画布位于位置 0,0(左上角)它没有像它应该的那样绘制。这是我的代码。

 function createImageOnCanvas(imageId){
    document.getElementById("imgCanvas").style.display = "block";
    document.getElementById("images").style.overflowY= "hidden";
    var canvas = document.getElementById("imgCanvas");
    var context = canvas.getContext("2d");
    var img = new Image(300,300);
    img.src = document.getElementById(imageId).src;
    context.drawImage(img, (0),(0));
}

function draw(e){
    var canvas = document.getElementById("imgCanvas");
    var context = canvas.getContext("2d");
    posx = e.clientX;
    posy = e.clientY;
    context.fillStyle = "#000000";
    context.fillRect (posx, posy, 4, 4);
}

HTML部分

 <body>
 <div id="images">
 </div>
 <canvas onmousemove="draw(event)" style="margin:0;padding:0;" id="imgCanvas"
          class="canvasView" width="250" height="250"></canvas> 

我读过有一种方法可以在 JavaScript 中创建一个简单的函数来获得正确的位置,但我不知道如何做到这一点。


简单的 1:1 场景

对于画布元素与位图大小为 1:1 的情况,您可以使用以下代码片段获取鼠标位置:

function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };
}

只需使用事件和画布作为参数从您的事件中调用它即可。它返回一个对象x and y对于鼠标位置。

由于您获得的鼠标位置是相对于客户端窗口的,因此您必须减去画布元素的位置才能将其转换为相对于元素本身的位置。

代码中集成的示例:

// put this outside the event loop..
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");

function draw(evt) {
  var pos = getMousePos(canvas, evt);

  context.fillStyle = "#000000";
  context.fillRect (pos.x, pos.y, 4, 4);
}

Note:如果直接应用于画布元素,边框和填充将影响位置,因此需要通过以下方式考虑getComputedStyle()– 或者将这些样式应用到父 div 上。

当Element和Bitmap大小不同时

当存在元素的大小与位图本身不同的情况时,例如,使用 CSS 缩放元素或存在像素长宽比等,您必须解决这个问题。

Example:

function  getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect(), // abs. size of element
    scaleX = canvas.width / rect.width,    // relationship bitmap vs. element for x
    scaleY = canvas.height / rect.height;  // relationship bitmap vs. element for y

  return {
    x: (evt.clientX - rect.left) * scaleX,   // scale mouse coordinates after they have
    y: (evt.clientY - rect.top) * scaleY     // been adjusted to be relative to element
  }
}

将变换应用于上下文(缩放、旋转等)

然后是更复杂的情况,您对上下文应用了变换,例如旋转、倾斜/剪切、缩放、平移等。为了处理这个问题,您可以计算当前矩阵的逆矩阵。

较新的浏览器允许您通过以下方式读取当前矩阵currentTransform属性和 Firefox(当前 alpha)甚至通过mozCurrentTransformInverted。然而,火狐浏览器通过mozCurrentTransform,将返回一个数组而不是DOMMatrix正如它应该。当通过实验标志启用时,Chrome 都不会返回DOMMatrix but a SVGMatrix.

然而,在大多数情况下,您必须实现自己的自定义矩阵解决方案(例如我自己的解决方案here– 免费/麻省理工学院项目),直到得到全力支持。

当您最终获得矩阵时,无论您采取何种路径来获得矩阵,您都需要将其反转并将其应用到鼠标坐标。然后,坐标被传递到画布,画布将使用其矩阵将其转换回当前所在的位置。

这样该点将位于相对于鼠标的正确位置。另外,在这里您需要调整坐标(在将逆矩阵应用于它们之前)以相对于元素。

仅显示矩阵步骤的示例:

function draw(evt) {
  var pos = getMousePos(canvas, evt);        // get adjusted coordinates as above
  var imatrix = matrix.inverse();            // get inverted matrix somehow
  pos = imatrix.applyToPoint(pos.x, pos.y);  // apply to adjusted coordinate
    
  context.fillStyle = "#000000";
  context.fillRect(pos.x-1, pos.y-1, 2, 2);
}

使用示例currentTransform实施时将是:

  var pos = getMousePos(canvas, e);          // get adjusted coordinates as above
  var matrix = ctx.currentTransform;         // W3C (future)
  var imatrix = matrix.invertSelf();         // invert

  // apply to point:
  var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e;
  var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f;

Update:我制作了一个免费解决方案(MIT),将所有这些步骤嵌入到一个易于使用的对象中,可以找到here并且还处理其他一些最容易忽视的细节问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

画布中的真实鼠标位置 的相关文章

随机推荐

  • Python 脚本在后台运行时挂起

    我有一个 Python 脚本 在 2 7 上运行 当我从命令行运行它时 它的行为与在后台运行时不同 当我从终端运行它时 它按预期运行 两个线程作为守护进程运行 将输出写入窗口 同时主循环等待退出命令 它会永远运行 直到我输入 quit py
  • 使用 GTK 查找工作区大小(屏幕大小减去任务栏)

    如何创建一个充满整个桌面的主窗口不覆盖任务栏 或被任务栏覆盖 and 没有被最大化 我可以使用以下命令找到整个屏幕尺寸并相应地设置主窗口 window gtk Window screen window get screen window r
  • dependencyManagement 和 Maven 中的依赖关系之间的区别

    有什么区别dependencyManagement and dependencies 我已经在 Apache Maven 网站上看到了文档 似乎在下面定义了一个依赖项dependencyManagement可以在其子模块中使用而无需指定版本
  • 将选取的图像保存到 CoreData

    我能够从照片库中选取并显示图像 但我的目标是能够将选取的图像或文件路径保存到核心数据 以便在选择保存的记录时该图像也会显示 我有 CoreData 工作 并且我能够显示 CoreData 中的文本 这只是图像阻碍了我 IBAction fu
  • 如何在 MATLAB 中以彩色打印字符串?

    通常当您在 MATLAB 中打印字符串时 disp this will print black letters 可以改为彩色打印吗 If you fprintf to stderr 它可以以另一种颜色出现 我认为这取决于您的喜好 有未记录的
  • 使用 Flask 路由捕获整数列表

    我正在尝试在 Flask 中实现一个基本计算器 我定义了两个 url 参数 当我只想添加两个值时这是可以管理的 但是 我想添加任意数量的值 如何在不编写无限长路线的情况下获得整数列表 app route add
  • 在talend中运行并行作业

    我遇到一种情况 我需要在talend 中并行运行五个不同的子作业 问题是 在我的选择查询中 我将获得五个不同的 ID 然后对于每个特定的 id 我需要运行五个不同的作业 tparrallelize 组件的问题是 它不允许我将上下文变量传递给
  • 是否有可能有一个“永久”占位符?

    我正在开发一个系统 其中包括一些文本框 用于测量温度 每分钟心率等 现在我只使用一个文本框 并在同一行的文本框后面添加单位 我的问题是空间相当有限 因此如果可能的话 我想在文本框中包含单位信息 例如右对齐 我了解 HTML5 占位符属性 但
  • Linux 上 backtrace() 的替代方案,可以查找静态函数的符号

    在手册页中 backtrace Linux 上的函数说 请注意 静态 函数的名称 没有暴露 并且在回溯中不可用 但是 启用调试符号后 g 像这样的程序addr2line and gdb仍然可以获得静态函数的名称 有没有办法从进程本身中以编程
  • 在 PHP 中从 mySQL 表填充下拉框

    我正在尝试使用 Php 中的 mySQL 查询结果填充下拉框 我在网上查找了示例 并在我的网页上尝试过它们 但由于某种原因 它们根本没有填充我的下拉框 我尝试调试代码 但在我查看的网站上并没有真正解释 而且我无法弄清楚每一行代码的含义 任何
  • C++ 专用模板函数接收文字字符串

    我正在编写一个具有许多专业化的模板方法 class FieldValue public template lt typename T gt void Set const T value 其中之一是 template lt gt void F
  • 在 JavaScript 中检查对象是否可序列化的可靠方法

    是否有已知的方法或库已经有一个帮助程序来评估对象是否可以在 JavaScript 中序列化 我尝试了以下方法 但它不涵盖原型属性 因此它提供了误报 isEqual obj JSON parse JSON stringify obj 还有另一
  • SQL Server 中用于寻址表的正确语法是什么?

    这似乎是一个相当明显的问题 但我无法想出合适的术语来表达我想要问的问题 因此为此提供参考材料一直很棘手 不过 答案似乎很明显 在检查 SQL Server 的 Pluralsight 培训材料时 他们建议始终引用 常规 查询 您可能为基本
  • gradle 构建在 lint 任务上失败

    我有一个使用 Android Studio 0 4 0 创建的简单 Android 项目 我使用 Gradle 1 9 和 Gradle Android Plugin 0 7 昨天我添加了杰克 沃顿的黄油刀库在我的 gradle 构建脚本中
  • Ruby:获取变量名称[重复]

    这个问题在这里已经有答案了 如何获得变量名 例如 def get var name var return variable name end myname nil get var name myname gt myname 最初目的 som
  • 如何使用 setuptools 打包 Python 守护进程

    如何使用 setuptools 打包 Python 应用程序 以便在安装时 例如通过 setup py 或 pip 将守护程序脚本放置在适当的位置 启动它 并将其标记为在启动时自动启动 就我而言 我的代码仅适用于 Linux 因此我只关心在
  • 无法打开 Hibernate 会话以进行事务、JavaConfig

    找不到错误 Spring MVC Hibernate JavaConfig 网络应用程序配置 package com sprhib init import java util Properties import javax annotati
  • 春天@RequestMapping

    我不断看到这种参数value redirect id in a RequestMappingSpring 的注释 我一直想知道什么是 id 这里 这是某种Expression Language 我所看到的示例代码 RequestMappin
  • 每页打印一次背景图像

    我需要每页打印一次背景图像当我打印大的 html 文件时 现在它只打印在第一页上 所以 css 的部分是 media all body text align left background image url C logo png back
  • 画布中的真实鼠标位置

    我正在尝试用鼠标在 HTML5 画布上进行绘制 但似乎效果良好的唯一方法是 如果我出于某种原因更改画布位置 则画布位于位置 0 0 左上角 它没有像它应该的那样绘制 这是我的代码 function createImageOnCanvas i