【问题标题】:Determining mouse position on an HTML5 canvas after zooming缩放后确定 HTML5 画布上的鼠标位置
【发布时间】:2020-02-12 03:23:11
【问题描述】:

我正在开发一些涉及使用画布的 HTML5 软件。有一个画布,我需要能够在其中缩放并允许用户通过鼠标单击在画布上涂鸦。到目前为止,在我找到的一些示例的帮助下,我已经开始使用缩放功能。问题是缩放后,我的绘图工具上的鼠标位置不正常。在任何缩放之前,我可以画得很好。这是缩放的代码:

//Zoom
        mainCanvas.onmousewheel = function(event) {
            var mousex = event.clientX - mainCanvas.offsetLeft;
            var mousey = event.clientY - mainCanvas.offsetTop;
            var wheel = event.wheelDelta / 120;
            //n or -n

            var zoom = 0;
            if(wheel < 0) {
                zoom = 1 / 2;
                if(currentzoom == 1)
                    return;
            } else {
                mousex = event.clientX - mainCanvas.offsetLeft;
                mousey = event.clientY - mainCanvas.offsetTop;
                zoom = 2;
                if(currentzoom == 32)
                    return;
            }
            currentzoom *= zoom;
            mainContext.translate(originx, originy);

            mainContext.scale(zoom, zoom);
            mainContext.translate(-(mousex / scale + originx - mousex / (scale * zoom ) ), -(mousey / scale + originy - mousey / (scale * zoom ) ));
            originx = (mousex / scale + originx - mousex / (scale * zoom ) );
            originy = (mousey / scale + originy - mousey / (scale * zoom ) );
            scale *= zoom;
            draw(mainContext, gridArray);
        }

就像我说的,缩放不是真正的问题,只是问题的根源。下面是为绘图工具确定鼠标位置的代码:

//this function determines the mouse position relative to the canvas element
        function ev_canvas(ev) {
            if(ev.layerX || ev.layerX == 0) {//Firefox, IE
                ev._x = ev.layerX;
                ev._y = ev.layerY;
            } else if(ev.offsetX || ev.offsetX == 0) {//Opera
                ev._x = ev.offsetX;
                ev._y = ev.offsetY;
            }

            var func = tool[ev.type];
            if(func) {
                func(ev);
            }
        }

我确定问题出在后面的代码块上,但我不确定是否要修复它。 任何帮助将不胜感激。

【问题讨论】:

  • 我不是画布方面的专家,但我想说你必须用你在上下文中使用的基本相同的(可能是一些反向的)变换来变换你的鼠标坐标。现在,当你点击左上角时,它可能会在整个图像的左上角绘制,即使你放大到不同的位置?
  • 我确实认为鼠标坐标需要进行类似的转换,我一直在摆弄它,但我还没有找到任何解决方案。至于缩放,它相对于鼠标位置(在鼠标位置的方向)缩放,它绘制的位置取决于我缩放的位置。我正在放大我绘制的彩色网格,并且在缩放后,我正在涂鸦的图像部分通常在画布上不可见。一般来说,你是对的。缩放后的涂鸦通常在实际鼠标位置的上方和左侧。
  • 你找到答案了吗?我也有同样的问题。

标签: javascript html canvas drawing dom-events


【解决方案1】:

我怀疑这是一段依赖于一些全局变量的代码,例如 currentzoom

所以,如果我对这个问题的理解正确,那么问题在于您如何使用画布进行鼠标控制和缩放。我怀疑当您缩放时,DOM 将鼠标光标放置在最初渲染的图片上它所属的位置。因此,如果您放大 200% 并将鼠标放在画布中心左侧 100 像素处,画布将表现得好像鼠标位于中心左侧 200 像素处。

currentzoom = 1;
originX = 0;
originY = 0;

function ev_canvas(ev) {
        if(ev.layerX || ev.layerX == 0) {//Firefox, IE
            ev._x = ev.layerX * currentzoom / 1 - originX;
            ev._y = ev.layerY * currentzoom / 1 - originY;
        } else if(ev.offsetX || ev.offsetX == 0) {//Opera
            ev._x = ev.offsetX * currentzoom / 1 - originX;
            ev._y = ev.offsetY * currentzoom / 1 - originY;
        }

        var func = tool[ev.type];
        if(func) {
            func(ev);
        }
    }

/ 1 被保留,以防将来用户想要将非“1”值设置为 currentzoom

【讨论】:

  • 对不起,我应该澄清一下:currentzoom 最初设置为 1。从那时起,它会发生变化,如代码的 sn-p 所示。不幸的是,解决方案并不是那么简单。缩放与鼠标位置协调工作,以便它向鼠标所在的任何位置缩放。我认为您的解决方案可能适用于更标准的缩放。
  • mainContext、originX、originY也是全局变量吗?如果您可以对所有全局变量进行显式声明,将会很有帮助。
【解决方案2】:

对于 Joomla 网站,您可以使用 Mouse Over Zoom - 这是一个 Joomla 扩展程序,可让您从 Joomla 网页查看更大版本的缩略图。现在您可以轻松浏览图片库:只需将鼠标光标移到缩略图上即可查看完整尺寸的图片,而无需加载新页面。在这里下载http://joomlaboat.com/mouse-over-zoom

如果不适合窗口,图片会自动调整大小。您可以自定义扩展,还有很多附加选项。为了加载透明图像,没有背景,只需使用 .png 图像。

【讨论】:

    【解决方案3】:

    试试这个:

    <!DOCTYPE HTML>
    <html>
        <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
            <style>
                body {
                    margin: 0px;
                    padding: 0px;
                }
    
                #wrapper {
                    position: relative;
                    border: 1px solid #9C9898;
                    width: 578px;
                    height: 200px;
                }
    
                #buttonWrapper {
                    position: absolute;
                    width: 30px;
                    top: 2px;
                    right: 2px;
                }
    
                input[type =
                "button"] {
                    padding: 5px;
                    width: 30px;
                    margin: 0px 0px 2px 0px;
                }
            </style>
            <script>
                function draw(scale, translatePos){
                    var canvas = document.getElementById("myCanvas");
                    var context = canvas.getContext("2d");
    
                    // clear canvas
                    context.clearRect(0, 0, canvas.width, canvas.height);
    
                    context.save();
                    context.translate(translatePos.x, translatePos.y);
                    context.scale(scale, scale);
                    context.beginPath(); // begin custom shape
                    context.moveTo(-119, -20);
                    context.bezierCurveTo(-159, 0, -159, 50, -59, 50);
                    context.bezierCurveTo(-39, 80, 31, 80, 51, 50);
                    context.bezierCurveTo(131, 50, 131, 20, 101, 0);
                    context.bezierCurveTo(141, -60, 81, -70, 51, -50);
                    context.bezierCurveTo(31, -95, -39, -80, -39, -50);
                    context.bezierCurveTo(-89, -95, -139, -80, -119, -20);
                    context.closePath(); // complete custom shape
                    var grd = context.createLinearGradient(-59, -100, 81, 100);
                    grd.addColorStop(0, "#8ED6FF"); // light blue
                    grd.addColorStop(1, "#004CB3"); // dark blue
                    context.fillStyle = grd;
                    context.fill();
    
                    context.lineWidth = 5;
                    context.strokeStyle = "#0000ff";
                    context.stroke();
                    context.restore();
                }
    
                window.onload = function(){
                    var canvas = document.getElementById("myCanvas");
    
                    var translatePos = {
                        x: canvas.width / 2,
                        y: canvas.height / 2
                    };
    
                    var scale = 1.0;
                    var scaleMultiplier = 0.8;
                    var startDragOffset = {};
                    var mouseDown = false;
    
                    // add button event listeners
                    document.getElementById("plus").addEventListener("click", function(){
                        scale /= scaleMultiplier;
                        draw(scale, translatePos);
                    }, false);
    
                    document.getElementById("minus").addEventListener("click", function(){
                        scale *= scaleMultiplier;
                        draw(scale, translatePos);
                    }, false);
    
                    // add event listeners to handle screen drag
                    canvas.addEventListener("mousedown", function(evt){
                        mouseDown = true;
                        startDragOffset.x = evt.clientX - translatePos.x;
                        startDragOffset.y = evt.clientY - translatePos.y;
                    });
    
                    canvas.addEventListener("mouseup", function(evt){
                        mouseDown = false;
                    });
    
                    canvas.addEventListener("mouseover", function(evt){
                        mouseDown = false;
                    });
    
                    canvas.addEventListener("mouseout", function(evt){
                        mouseDown = false;
                    });
    
                    canvas.addEventListener("mousemove", function(evt){
                        if (mouseDown) {
                            translatePos.x = evt.clientX - startDragOffset.x;
                            translatePos.y = evt.clientY - startDragOffset.y;
                            draw(scale, translatePos);
                        }
                    });
    
                    draw(scale, translatePos);
                };
    
    
    
                jQuery(document).ready(function(){
                   $("#wrapper").mouseover(function(e){
                      $('#status').html(e.pageX +', '+ e.pageY);
                   }); 
                })  
            </script>
        </head>
        <body onmousedown="return false;">
            <div id="wrapper">
                <canvas id="myCanvas" width="578" height="200">
                </canvas>
                <div id="buttonWrapper">
                    <input type="button" id="plus" value="+"><input type="button" id="minus" value="-">
                </div>
            </div>
            <h2 id="status">
            0, 0
            </h2>
        </body>
    </html>
    

    鼠标移动轨迹非常适合我.. Njoy!!!

    【讨论】:

      【解决方案4】:

      我有一个更好的脚本来获取画布上的鼠标位置:

      function writeMessage(canvas, message) {
              var context = canvas.getContext('2d');
              context.clearRect(0, 0, canvas.width, canvas.height);
              context.font = '18pt Calibri';
              context.fillStyle = 'black';
              context.fillText(message, 10, 25);
            }
            function getMousePos(canvas, evt) {
              var rect = canvas.getBoundingClientRect(), root = document.documentElement;
      
              // return relative mouse position
              var mouseX = evt.clientX - rect.top - root.scrollTop;
              var mouseY = evt.clientY - rect.left - root.scrollLeft;
              return {
                x: mouseX,
                y: mouseY
              };
            }
      
            window.onload = function() {
              var canvas = document.getElementById('myCanvas');
              var context = canvas.getContext('2d');
      
              canvas.addEventListener('mousemove', function(evt) {
                var mousePos = getMousePos(canvas, evt);
                var message = "Mouse position: " + mousePos.x + "," + mousePos.y;
                writeMessage(canvas, message);
              }, false);
            };
      

      试试看,有什么问题可以评论。

      【讨论】:

        猜你喜欢
        • 2014-08-18
        • 2014-08-27
        • 2018-02-01
        • 2014-04-16
        • 2018-03-07
        • 2021-09-22
        • 2021-11-18
        • 2018-08-21
        相关资源
        最近更新 更多