使用isPointInPath()和响应式设计

时间:2015-05-04 12:20:05

标签: javascript jquery html5 jquery-mobile canvas

我有一个正确绘制的画布对象数组。我有三个问题:

  1. 偏移。我已经在JS小提琴中测试了下面的代码并且它可以工作,但是当我将它导出到我的网页时,变量会出现偏差。检测发生,但不是在正确的地方。页面宽度在CSS中设置,实际画布区域使用margin:0自动调用居中,但它小于页面宽度。
  2. <canvas id="canvas" width="780" height="690" style="position:absolute;"></canvas>
    
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var $canvas = $("#canvas");
    var canvasOffset = $canvas.offset();
    var offsetX = canvasOffset.left;
    var offsetY = canvasOffset.top;
    var scrollX = $canvas.scrollLeft();
    var scrollY = $canvas.scrollTop();
    
    var $results = $("#results");
    
    // define the polygon items 
    var polyArray = new Array (6);
    polyArray [0] =[{x:50,y:236}, {x:200,y:115}, {x:350,y:50}, {x:350,y:300}, {x:232,y:325}, {x:75,y:300}];
    polyArray [1] =[{x:350,y:55}, {x:350,y:300}, {x:510,y:300}, {x:510,y:205}, {x:578,y:172}, {x:690,y:96}, {x:650,y:17}];
    polyArray [2] =[{x:510,y:300}, {x:510,y:200}, {x:715,y:113}, {x:780,y:200}, {x:780,y:485}, {x:625,y:468}, {x:605,y:456}, {x:605,y:428}];
    polyArray [3] =[{x:0,y:446}, {x:284,y:320}, {x:255,y:540}, {x:240,y:566}, {x:73,y:600}, {x:0,y:565}];
    polyArray [4] =[{x:355,y:305}, {x:510,y:305}, {x:604,y:423}, {x:604,y:460}, {x:628,y:484}, {x:610,y:513}, {x:587,y:468}, {x:537,y:426}, {x:500,y:400}, {x:447,y:424}, {x:312,y:365}, {x:307,y:314 }];
    polyArray [5] =[{x:350,y:425}, {x:415,y:421}, {x:455,y:434}, {x:495,y:411}, {x:550,y:444}, {x:618,y:590}, {x:570,y:616}, {x:359,y:597}, {x:333,y:522}];
    
    // call the function to draw all the objects in the array
    define(polyArray);
    // call through the array to draw the objects
    function define(polygon) { 
        ctx.beginPath();
        for (var i = 0; i < polygon.length; i++) {
            ctx.moveTo(polygon[i][0].x, polygon[i][0].y);
            for (var j = 1; j < polygon[i].length; j++) {
                ctx.lineTo(polygon[i][j].x, polygon[i][j].y);
            }
            ctx.fill();
        }
        ctx.closePath();
    
    }   
    function hitTest(polygon) {
        // redefine the polygon
        define(polygon);
        // ask isPointInPath to hit test the mouse position
        // against the current path
        return (ctx.isPointInPath(mouseX, mouseY));
    }
    
    function handleMouseMove(e) {
        e.preventDefault();
        mouseX = parseInt(e.clientX - offsetX);
        mouseY = parseInt(e.clientY - offsetY);
    
        // check if the mouse is inside the polygon
            var isInside = hitTest(polyArray);
            if (isInside) {
                canvas.style.cursor = 'pointer';
                $results.text("Mouse is inside the area);
            } else {
                canvas.style.cursor = 'default';
                $results.text("Outside");
            }
    }
    $("#canvas").mousemove(function (e) {
        handleMouseMove(e);
    });
    
    1. 检测哪个物体悬停在上面。需要发生的是在悬停一个数组形状应该影响一些CSS / JS。如何分配ID变量并检测它?

    2. 当我将响应式设计纳入等式时,我对于如何合并这个偏移和聚合物以适当缩放有点困惑。

    3. 非常感谢正确方向的任何一点。

1 个答案:

答案 0 :(得分:1)

问题#1:在画布移动后获得准确的鼠标位置

每当您移动画布(fex:margin: 0 auto)时,您必须重新计算offsetXoffsetY值:

如果您手动更改画布元素的CSS(在javascript中为fex:canvas.style.margin='50px'),那么您还必须手动调用reOffset()

// cache the canvas's offset positions since the
// offset positions are used often
var offsetX,offsetY;

// call this once at the beginning of your app
// and whenever you change the canvas's position on the page
// (eg call when you change margins, scroll, etc)
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}

// have the browser auto-reset offsetX & offsetX when 
// the viewport scrolls or resizes
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }

问题#2检测悬停&amp;模糊多边形

您的hitTest函数将测试鼠标当前是否在指定的多边形内。因此,在handleMousemove内,您可以为hitText内的每个多边形调用polyArray

保持一个标志变量,指示鼠标所在的最后一个多边形的索引#(或-1表示鼠标在所有多边形之外。当你的标志变量值改变时,你知道有一个悬停事件或者模糊事件。比较最后和当前的标志变量,以确定哪个多边形现在悬停或模糊。

问题#3采用响应式设计

浏览器向e.clientXe.clientY报告的鼠标坐标始终处于相对于浏览器视口的未缩放值。

所以如果你:

  • 单击鼠标并使用e.clientX / e.clientY确定鼠标位于[100,100],
  • 缩放画布:context.scale(2,2),
  • 在不将鼠标移动到原始[100,100]位置的情况下重新点击

然后:

使用e.clientX / e.clientY检测鼠标坐标仍然会将位置报告为[100,100],即使画布已缩放且鼠标相对于缩放画布为[200,200]

修复:

您必须缩放浏览器报告的鼠标位置以匹配画布的缩放系数:

// Determine how much you want to scale the canvas
var scaleFactor=2.00;

// scale the canvas
context.scale(scaleFactor,scaleFactor);

// also scale the mouse position reported by the browser
mouseX=parseInt(e.clientX-offsetX)*scaleFactor;
mouseY=parseInt(e.clientY-offsetY)*scaleFactor;