我正在使用Chart.js 4.4.0创建一个具有十字准线效果的图表,类似于Flot.js crosshair
插件。在this YouTube guide之后,我生成了以下示例代码:
<html>
<head>
<script type="text/javascript" src="../include/chart-4.4.0.umd.js"></script>
</head>
<body>
<div id="chart_container" class="plot" style="width:50%;">
<div>
<canvas id="myChart"></canvas>
</div>
</div>
<script>
/* The Chart.js context */
const ctx = document.getElementById('myChart');
/* The Chart container node, used for crosshair */
let container = document.getElementById('chart_container');
let chart_data = {
datasets: [{
data: [{x:0, y:1}, {x:1, y:1}, {x:1, y:2}, {x:2, y:2},
{x:2, y:3}, {x:3, y:3}, {x:3, y:1}, {x:4, y:1}],
borderWidth: 3,
/* For the crosshair to work, we must disable other
* tooltip hover effects: */
pointHoverRadius: 0,
pointHitRadius: 0,
pointRadius: 0
}]
};
/* Chart.js chart options object for the Chart.js
* constructor, defined below. */
let chart_options = {
showLine: true,
pointStyle: false,
borderColor: 'rgba(255,204,0,1)',
borderWidth: 1,
fill: '+1',
scales: {
y: {beginAtZero: true}
},
};
/* Create the Chart.js chart */
let cjs_plot = new Chart(ctx, {
type: 'scatter',
data: chart_data,
options: chart_options,
});
/* Implementing the crosshair effect previously done
* using the Flot.js 'crosshair' plugin. */
/* https://www.youtube.com/watch?v=za2cQFObvWQ */
container.addEventListener('mousemove', (e) => {
crosshair(cjs_plot, e);
})
function crosshair(chart, mousemove) {
/* Setting `update` to 'none' means the refresh is
* invisible so that we don't see previous crosshair
* lines as the mousemoves. */
chart.update('none');
//console.log(mousemove);
const x = mousemove.offsetX;
const y = mousemove.offsetY;
const { ctx, chartArea: {top, bottom, left, right, width, height} } = chart;
ctx.save();
/* Draw items */
/* rgba(255,0,0,1) is solid red */
ctx.strokeStyle = 'rgba(255,0,0,1)';
ctx.lineWidth = 1;
/* Only draw crosshairs if mouse is inside the chart area.
* Remember 'y' is measured top-down. */
if(x >= left && x <= right && y >= top && y <= bottom) {
/* Draw horizontal line */
ctx.beginPath();
ctx.moveTo(left, y);
ctx.lineTo(right, y);
ctx.stroke();
ctx.closePath();
/* Draw vertical line */
ctx.beginPath();
ctx.moveTo(x, top);
ctx.lineTo(x, bottom);
ctx.stroke();
ctx.closePath();
}
ctx.restore();
} // End of crosshair() function
</script>
</body>
</html>
字符串
当用户将鼠标移到图表上时,这将成功创建十字准线。
问题是,如果我将鼠标指针快速移出图表,线条并不总是以应有的方式消失。它们只是停留在我将鼠标移出的边缘附近。这种情况并不总是发生,当我慢慢穿过边缘时几乎不会发生。这几乎就像代码无法“注册”光标是否移动过快而超出其边界。
This question描述了一个类似的问题,但提供的唯一解决方案是将侦听器附加到图表的包含节点,而不是图表本身或HTML <body>
。
This answer也解决了这个问题,但只提供了如何解决这个问题的一般描述。我打算开始尝试这个建议,但我预计这将需要一两周的努力,所以我在这里发帖,希望有人会有更好的解决方案或工作代码在此期间发布。(这个答案已经超过13年了,所以现在有一个更好的解决方案是合理的希望)。
我如何调整上面的代码,以保证无论指针移动的速度如何,只要指针在图表区域之外,十字准线就会消失?
1条答案
按热度按时间nwwlzxa71#
对
chart.update('none');
的调用绘制了没有十字准线的图表,函数crosshairs
中的所有后续操作都是绘制实际的十字准线线。这意味着要删除十字准线,您的方法依赖于在图表容器内部但在
chartArea
外部触发的mousemove
事件,因此if
条件(x >= left && x <= right && y >= top && y <= bottom)
至少为false
一次(这是唯一的情况下,当chart.update('none')
是 * 不 * 后跟着线条绘制)这是mousemove
应该触发的一个非常小的边界,这就是为什么它很容易被(不是很)快速的鼠标移动跳过。删除十字准线的正确方法是为
mouseleave
注册一个处理程序,该处理程序只绘制图表而不绘制其他内容:字符串
下面是您的代码片段,
的数据