画布中的链接(HTML5)

时间:2015-09-02 16:09:09

标签: javascript html css html5 canvas

我已经知道如何实现用户界面,我已经做到了。但在某些时刻我的FPS较低。通过使用Firefox进行性能测试,我注意到那些时刻是浏览器重新计算CSS的时候。

它必须重新计算CSS,因为我修改了属性" style"通过插入css规则" cursor:pointer"。我这样做是因为在我的画布中有一些需要不同光标的链接。但我想优化该功能以避免冻结。关于如何做到的任何想法?

我的代码执行此操作:将addEventHandler添加到canvas(mousemove),每次事件触发时都会检查光标坐标,如果我的光标坐标为ON,则将光标更改为"指针",它还会设置一个名为hoverIndex的变量,指向数组中链接的位置。

var sky = new Image();
var logotype = new Image();
var back_btn = new Image();
var next_btn = new Image();
var upgrades_btn = new Image();

var coin_five = new Image();
var coin_ten = new Image();
var coin_fifty = new Image();
var cash_hundred = new Image();

var currentArea = "main_menu";
var cvn, ctx;

var linkAreas = [];
var hoverIndex = -1;

var gameVersion = "1.2.2a";

var coinFiveReset = 1500;
var coinTenReset = 5000;
var coinFiftyReset = 10000;
var coinHundredReset = 10000;

var coinFiveRemaining = 1500;
var coinTenRemaining = -1;
var coinFiftyRemaining = -1;
var coinHundredRemaining = -1;

var playingInterval;

//{type: "five", x: 0, y: 0}
var coinsPlaying = [];

function initialization(){
    cvn = document.getElementById("kg_coinfactory");
    ctx = cvn.getContext("2d");

    cvn.addEventListener("mousemove", function(ev){
        var pos = getMousePosition(ev);
        for(var x = 0; x<linkAreas.length; x++)
            if(currentArea == linkAreas[x].area && pos.x >= linkAreas[x].x && pos.y >= linkAreas[x].y && pos.x <= linkAreas[x].x + linkAreas[x].width && pos.y <= linkAreas[x].y + linkAreas[x].height)
            {
                hoverIndex = x;
                cvn.style = "cursor: pointer";
                break;
            }
            else
            {
                cvn.style = "";
                hoverIndex = -1;
            }
    });

    cvn.addEventListener("mouseup", function(){
        if(hoverIndex != -1)
            linkAreas[hoverIndex].onClickFunc();
    });
}

function getMousePosition(ev){
    var rect = cvn.getBoundingClientRect();
    return {x: ev.clientX - rect.left, y: ev.clientY - rect.top};
}

function registerLink(x, y, text, area, ctx, onClickFunc)
{
    var s = ctx.measureText(text);
    linkAreas.push({x: x, y: y - 24, width: s.width, height: 24, area: area, onClickFunc: onClickFunc});
}

1 个答案:

答案 0 :(得分:1)

FPS真的让人担心吗?

无论如何,您可以保存光标的现有状态,只有当光标移入或移出悬停区域时才能更改它。

或者,如果你不需要画布来响应悬停区域下的鼠标事件,你可以在画布上position:absolute一个DOM元素,让该元素响应悬停&amp;点击活动。

或者,您可以在画布上关闭指针并将自己的指针绘制成ImageImage。

或者,在极端情况下,您甚至可以在现有画布上覆盖第二个画布,并将drawImage仅覆盖在第二个画布上的指针上。在第二个画布上设置pointer-events:none,以便将鼠标事件切换到现有的底层画布。

BTW,您的鼠标位置计算可以更有效。

每次mousemove事件都会getMousePosition调用getBoundingClientRect。相反,保存rect.leftrect.top并使用保存的offsetX&amp; offsetY值而不是使用更昂贵的getBoundingClientRect()。如果窗口调整大小或滚动,则必须重新计算边界框。以下是如何执行此操作的示例:

var offsetX,offsetY;
reOffset();

function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}

window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }

调用外部函数(你getMousePosition)会导致一些额外的处理,因此你可以直接在鼠标事件处理程序中计算鼠标位置。

此外,由于您自己处理mousemove事件,因此可以通过告诉浏览器不需要将此事件冒泡到其他元素来保存处理:

// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();

因此,更高效的鼠标事件处理程序可能如下所示:

cvn.addEventListener("mousemove", function(ev){    

    // tell the browser we're handling this event
    ev.preventDefault();
    ev.stopPropagation();

    // calc the mouse position directly in the handler
    // and use cached offset values
    mouseX=parseInt(ev.clientX-offsetX);
    mouseY=parseInt(ev.clientY-offsetY);

    ... and now do stuff ...

}