html5 canvas tooltip javascript闪烁

时间:2017-03-02 10:18:22

标签: javascript jquery html5 canvas tooltip

我在html5

上遇到了画布工具提示的问题

一切似乎都很顺利,但是当我在画布右上角附近左/右计算画布工具提示时(显示工具提示不在画布外),然后他开始闪烁。

有时他甚至没有显示工具提示,而x和y坐标与上次相同。

html aspx页面代码:

<canvas id="CanvasToolTip"  width="275" height="75" style="z-index: 3"></canvas>

使用Javascript:

var canvasToolTip = canvasLayer = document.getElementById("CanvasToolTip"); //Get the canvasToolTip object
var canvasToolTipContent = canvasToolTip.getContext("2d");



var handleMouseOverForToolTip = function (e) {
    e.preventDefault();
    e.stopPropagation();

    if (listPoints.length > 0) {
        var canvasOffset = $("#CanvasPlan").offset();
        var offsetX = canvasOffset.left;
        var offsetY = canvasOffset.top;

        var tooltipXCorrection = 10;

        var tooltipHeight = 75;
        var tooltipWidth = 275;

        var canvasPlanHeight = canvasPlan.getHeight();
        var canvasPlanWidth = canvasPlan.getWidth();

        var mouseX = parseInt(e.pageX - offsetX);
        var mouseY = parseInt(e.pageY - offsetY);

        var enableToolTip = false;
        for (var i = 0; i < listPoints.length; i++) {
            var point = listPoints[i];
            var dx = mouseX - point.xZ;
            var dy = mouseY - point.yZ;

            if (dx * dx + dy * dy < toolTipRadius && point.draw === true) {
                var diffX = canvasPlanWidth - (point.xZ + tooltipWidth);
                var diffY = canvasPlanHeight - (point.yZ + tooltipHeight);

                //checks if toolbar difference is more then -120, then change the position more to left
                if (diffX < -120) {
                    canvasToolTip.style.left = (point.xZ + (diffX / 2 + diffX / 3)) + "px";
                } else if (diffX <= -90) {
                    canvasToolTip.style.left = (point.xZ + (diffX / 2 + diffX / 4)) + "px";
                } else {
                    canvasToolTip.style.left = (point.xZ + tooltipXCorrection) + "px";
                }

                if (diffY < -5) {
                    canvasToolTip.style.top = (point.yZ - tooltipHeight) + "px";
                } else {
                    canvasToolTip.style.top = (point.yZ) + "px";
                }

                canvasToolTipContent.clearRect(0, 0, canvasToolTip.width, canvasToolTip.height);
                canvasToolTipContent.fillStyle = "white";
                canvasToolTipContent.font = "13px Verdana";
                canvasToolTipContent.fillText(pointName + ": " + point.name, 10, 20);
                enableToolTip = true;
            }
        }

        if (!enableToolTip) {
            canvasToolTip.style.left = "-500px";
        }
    }
};

也许handleMouseOverForToolTip函数正在进行多次计算?

1 个答案:

答案 0 :(得分:0)

同步显示刷新以停止闪烁和剪切。

动画和常常显示图形的闪烁和剪切的最常见原因与显示刷新不同步。

为了显示图像,显示硬件扫描显示RAM,一次显示一个像素到显示器。此过程需要一些时间,如果您要显示新内容,则直到下次扫描这些像素时才会显示。如果在过渡期间在该位置上绘制了其他东西,例如背景,则下一次扫描可以显示背景。根据时间的不同,你会得到一些帧而不是其他帧。结果是闪烁。

如果您正在显示的图形在显示扫描相同区域时显示,则您可能只看到一半渲染。这称为剪切(在动画剪切中,会在某个随机(或常规)点上切割屏幕上一条线上的移动物体)。

使用requestAnimationFrame

进行同步

要修复闪烁和剪切,您需要同步到显示器,并确保渲染的所有内容都在下一帧开始时显示在显示RAM中,而不是中途或随机显示,例如输入事件。

要同步到显示屏,请使用requestAnimationFrame。它确保您呈现给显示元素(例如画布)的内容仅在下一次显示刷新开始时显示给显示。

鼠标事件

对于您的问题,您应该使用鼠标事件来记录相关的鼠标详细信息,并使用动画循环显示与刷新同步的工具提示。

const mouse = {
    x : 0,
    y : 0,
    update : true,  // to prevent unneeded updates of the display
}
function mouseEvent(event){
    if(event.pageX !== mouse.x || event.pageY !== mouse.y){
         mouse.update = true;
         mouse.x = event.pageX;
         mouse.y = event.pageY;
     }
 }

显示

通过requestAnimationFrame调用显示循环。这在大多数系统上都是60fps,但在极少数情况下会更高。但速度与此问题无关。重要的是浏览器知道函数中呈现的内容需要延迟到显示刷新。

function displayLoop(time){ // time is hi res time passed by the browser
    if(mouse.update){  // has the position of the mouse changed
        mouse.update = false; // clear the update semaphore
        createToolTip(); // render the tool tip 
    }
    requestAnimationFrame(displayLoop); // request next animation frame
    // the function exits now. Normally at this point the changed elements
    // are presented to the display RAM but as this is a special function
    // call the changed DOM elements are held in the offscreen buffer 
    // until the next display refresh
}
requestAnimationFrame(displayLoop); // start displaying

根据正在渲染的其他内容,您可能还需要编写工具提示,而不是仅在鼠标移动时更新工具提示。只需修改上面的内容即可忽略鼠标更新信号量。