我想重写使用Chart.js vizwit,我很难找出如何获得日期/时间图交互工作。如果您尝试在this demo上选择日期范围,则会看到它过滤了其他图表。我如何让Chart.js让我在时间尺度图上选择一个范围?它似乎默认情况下只能让我点击某个特定的日期点。我如何选择日期范围(如onClick,但拖动/选择)
谢谢你的时间。
我想重写使用Chart.js vizwit,我很难找出如何获得日期/时间图交互工作。如果您尝试在this demo上选择日期范围,则会看到它过滤了其他图表。我如何让Chart.js让我在时间尺度图上选择一个范围?它似乎默认情况下只能让我点击某个特定的日期点。我如何选择日期范围(如onClick,但拖动/选择)
谢谢你的时间。
以@ jordanwillis's和你的答案为基础,通过在图表上放置另一个画布,可以轻松实现任何你想要的。
只需将pointer-events:none
添加到它的样式中,以确保它不会干扰图表的事件。
无需使用注释插件。
例如(在这个例子中canvas
是原始图表画布,overlay
是您的新画布放置在顶部):
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false
}
}]
}
}
}
var canvas = document.getElementById('chartJSContainer');
var ctx = canvas.getContext('2d');
var chart = new Chart(ctx, options);
var overlay = document.getElementById('overlay');
var startIndex = 0;
overlay.width = canvas.width;
overlay.height = canvas.height;
var selectionContext = overlay.getContext('2d');
var selectionRect = {
w: 0,
startX: 0,
startY: 0
};
var drag = false;
canvas.addEventListener('pointerdown', evt => {
const points = chart.getElementsAtEventForMode(evt, 'index', {
intersect: false
});
startIndex = points[0]._index;
const rect = canvas.getBoundingClientRect();
selectionRect.startX = evt.clientX - rect.left;
selectionRect.startY = chart.chartArea.top;
drag = true;
// save points[0]._index for filtering
});
canvas.addEventListener('pointermove', evt => {
const rect = canvas.getBoundingClientRect();
if (drag) {
const rect = canvas.getBoundingClientRect();
selectionRect.w = (evt.clientX - rect.left) - selectionRect.startX;
selectionContext.globalAlpha = 0.5;
selectionContext.clearRect(0, 0, canvas.width, canvas.height);
selectionContext.fillRect(selectionRect.startX,
selectionRect.startY,
selectionRect.w,
chart.chartArea.bottom - chart.chartArea.top);
} else {
selectionContext.clearRect(0, 0, canvas.width, canvas.height);
var x = evt.clientX - rect.left;
if (x > chart.chartArea.left) {
selectionContext.fillRect(x,
chart.chartArea.top,
1,
chart.chartArea.bottom - chart.chartArea.top);
}
}
});
canvas.addEventListener('pointerup', evt => {
const points = chart.getElementsAtEventForMode(evt, 'index', {
intersect: false
});
drag = false;
console.log('implement filter between ' + options.data.labels[startIndex] + ' and ' + options.data.labels[points[0]._index]);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.js"></script>
<body>
<canvas id="overlay" width="600" height="400" style="position:absolute;pointer-events:none;"></canvas>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
</body>
注意到,我们立足我们的活动,并在原来的坐标画布,但我们绘制覆盖。这样我们就不会弄乱图表的功能。
不幸的是,没有像这样的东西被内置到chart.js中。您必须实现您自己的事件挂钩和处理程序,这些挂钩和处理程序会在图表上呈现突出显示的部分,然后使用原型方法来确定哪些数据已突出显示。即使这些内置的钩子可能不足以实现你想要的东西。
事件钩选项是:
添加的事件处理程序的画布元件本身上(见下面的例子)
canvas.onclick = function(evt){
var activePoints = myLineChart.getElementsAtEvent(evt);
// => activePoints is an array of points on the canvas that are at the same position as the click event.
};
使用onClick
添加事件处理程序的chart.js之图表对象上配置选项(explained here)。
扩展一些核心图表事件挂钩并添加自己的。 (有关指导,请参见here)。
假设这种方法可行,那么你可以再相应地过滤原始的图表数据阵列(在基础chart.js之对象),并调用.update()
原型法绘制新图。
根据@jordanwillis'几个月后更新'回答:我已经有了范围选择的开始。
canvas.onpointerdown = function (evt) {
clearAnnotations()
const points = chart.getElementsAtEventForMode(evt, 'index', { intersect: false })
const label = chart.data.labels[points[0]._index]
addAnnotation(label)
}
canvas.onpointerup = function (evt) {
const points = chart.getElementsAtEventForMode(evt, 'index', { intersect: false })
const label = chart.data.labels[points[0]._index]
addAnnotation(label)
}
function clearAnnotations() {
if (chart.options.annotation) {
chart.options.annotation.annotations = []
}
}
function addAnnotation (label) {
const annotation = {
scaleID: 'x-axis-0',
type: 'line',
mode: 'vertical',
value: label,
borderColor: 'red'
}
chart.options.annotation = chart.options.annotation || {}
chart.options.annotation.annotations = chart.options.annotation.annotations || []
chart.options.annotation.annotations.push(annotation)
chart.update()
}
仍需要弄清楚如何显示视觉悬停指标,因为在这个问题联系了演示,但它是一个开始。
非常感谢!这个例子看起来不错。 –
不客气,很高兴帮助 –