javascript - 定位鼠标相对于变换平面的位置

标签 javascript css canvas css-transforms

我已经设置了一个 jsfiddle 来说明我的情况:http://jsfiddle.net/j5o0w5qc/1/

基本上,我有三个嵌套的 HTML 元素:外部的视口(viewport) div、中间的舞台 div 和内部的 Canvas 。舞台 div 为应用于 Canvas 的 3d 变换提供透视设置。视口(viewport)有 overflow: hidden; 所以我们看不到视口(viewport)之外的任何东西。它还附加了一个监听器,用于监听 mousedown

在我正在构建的实际应用程序中, Canvas 可能会转换为任意 3d 转换,涉及 3d 空间中的平移和旋转。我想要发生的是让视口(viewport) div 拦截点击,并在 Canvas 上点击的地方画一个点。我正在使用视口(viewport) div 拦截事件,并且在 Chrome 中使用 offsetX 和 offsetY。这对 Chrome 非常有用,但我知道我不能依赖其他浏览器中的 offsetX 和 offsetY,所以我想使用 pageX 和 pageY,通过 jQuery 规范化,但我不太确定该怎么做。

我目前在 jsfiddle 中获得的内容在 Chrome 中运行良好,除非您在视口(viewport)中单击而不是在 Canvas 上。当您单击 Canvas 时,它会在那里绘制一个点,而不管 Canvas 的变换如何。 Chrome 正在做所有艰苦的工作,并通过 offsetX 和 offsetY 为我提供我想要的东西。但是,当您在不在 Canvas 上的视口(viewport)中单击时,我想它会给我相对于视口(viewport)而不是 Canvas 的 offsetX 和 offsetY 值,然后解释它并在 Canvas 上绘制一个点。例如,如果我变换 Canvas 然后单击视口(viewport)的右上角,则 Canvas 的右上角会出现一个点,而不管该 Angular 实际出现在页面上的什么位置。

然而,在 Firefox 中,只要没有对 Canvas 应用任何变换,它就可以很好地工作,但是一旦 Canvas 被变换,突然之间,绘制的点就会移位,我想不通弄清楚如何获取我的 pageX 和 pageY 值并找出我在 Canvas 中单击的确切位置。

有没有人有什么绝妙的解决方案?我一直在为这个问题苦苦思索太久了。我很确定我需要手动计算一些 3d 变换矩阵或其他东西,我花了几个小时编写方法来返回矩阵的逆矩阵,将矩阵乘以向量,以及各种各样的东西,但没有它实际上已经为我解决了问题,我不确定我错过了什么。

Stackoverflow 说 jsfiddle 链接需要代码,所以这是我的所有代码:

HTML:

<div id="viewport">
    <div id="stage">
        <canvas id="myCanvas" width="300" height="300"></canvas>
    </div>
</div>

<div id="stuff">
    <button onclick="transformMe()">Transform</button>
    <input id="blah" type="text" size="45"></input>
</div>

CSS:

#viewport, #stage, #myCanvas {
    width: 300px;
    height: 300px;
    position: absolute;
    top: 0;
    left: 0;
}

#viewport {
    border: 1px solid #000;
    overflow: hidden;
}

#stage {
    perspective: 1000px;
    transform-style: preserve-3d;
}

#myCanvas {
    background-color: green;
    transform-style: preserve-3d;
}

#stuff {
    position: absolute;
    top: 350px;
}

Javascript:

var counter = 0;

$('#viewport').mousedown(function _drawOnCanvas (e)
{
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var xpos, ypos;

    if (typeof e.offsetX=='undefined')
    {
        xpos = e.pageX - $('#myCanvas').offset().left;
        ypos = e.pageY - $('#myCanvas').offset().top;
    }
    else
    {
        xpos = e.offsetX;
        ypos = e.offsetY;
    }


    ctx.fillRect(xpos-5, ypos-5, 10, 10);
});

function transformMe()
{
    counter++;
    var angle = (counter * 30) % 360;
    $('#myCanvas').css('transform','perspective(1000px) rotate3d(5,6,7,' + angle + 'deg)');
    $('input').val('counter: ' + counter + ', angle: ' + angle);
};

最佳答案

对于 Firefox,您可以使用 event.layerXevent.layerY .将它们视为 Firefox 的 offsetXoffsetY 版本。

演示:http://jsfiddle.net/dirtyd77/j5o0w5qc/3/

JavaScript:

var counter = 0;

$('#viewport').mousedown(function _drawOnCanvas (e)
{
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var xpos, ypos;

    if (typeof e.offsetX=='undefined')
    {
        xpos = e.originalEvent.layerX;
        ypos = e.originalEvent.layerY;
    }
    else
    {
        xpos = e.offsetX;
        ypos = e.offsetY;
    }


    ctx.fillRect(xpos-5, ypos-5, 10, 10);
});

function transformMe()
{
    counter++;
    var angle = (counter * 30) % 360;
    $('#myCanvas').css('transform','perspective(1000px) rotate3d(5,6,7,' + angle + 'deg)');
    $('input').val('counter: ' + counter + ', angle: ' + angle);
};

关于javascript - 定位鼠标相对于变换平面的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26070194/

相关文章:

jquery - 淡入淡出一次分页 2 个元素

javascript - 你如何检测 three.js 中粒子系统中的粒子悬停?

javascript - 使用(鼠标+其他键)绘制线条

HTML5 Canvas 图片变色

javascript - React 中带有延迟子菜单 View 的菜单

javascript - Angular UI-Router抽象父状态解析数据

javascript - 刷新页面时Angular js给出404错误

javascript - 服务器应该如何响应 Backbone 同步

html - Bootstrap 3 拉和推不按预期运行

html - 尽管有多个网格元素,为什么我的网格容器没有展开?