我在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函数正在进行多次计算?
答案 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
根据正在渲染的其他内容,您可能还需要编写工具提示,而不是仅在鼠标移动时更新工具提示。只需修改上面的内容即可忽略鼠标更新信号量。